diff options
author | Alex Sakhartchouk <alexst@google.com> | 2011-02-22 10:30:32 -0800 |
---|---|---|
committer | Alex Sakhartchouk <alexst@google.com> | 2011-02-22 10:30:32 -0800 |
commit | c29a4442812d5f0e9f1af13b36cb6a806b6b46e0 (patch) | |
tree | 65a6b04a509557293f56d6c14d99daffafc568dd /tests/RenderScriptTests/ImageProcessing/src | |
parent | bdbdf0148d8ad36f8425b9be81c03dbe81333354 (diff) | |
download | frameworks_base-c29a4442812d5f0e9f1af13b36cb6a806b6b46e0.zip frameworks_base-c29a4442812d5f0e9f1af13b36cb6a806b6b46e0.tar.gz frameworks_base-c29a4442812d5f0e9f1af13b36cb6a806b6b46e0.tar.bz2 |
Moving renderscript tests away from the library to a dedicated test folder.
Change-Id: I7d8e20a17513f167eae3681d77463c01f4fa24a7
Diffstat (limited to 'tests/RenderScriptTests/ImageProcessing/src')
5 files changed, 672 insertions, 0 deletions
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java new file mode 100644 index 0000000..4f2f52ab --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2009 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.app.Activity; +import android.os.Bundle; +import android.graphics.BitmapFactory; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.renderscript.ScriptC; +import android.renderscript.RenderScript; +import android.renderscript.Type; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Script; +import android.view.SurfaceView; +import android.view.SurfaceHolder; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; +import android.view.View; +import java.lang.Math; + +public class ImageProcessingActivity extends Activity + implements SurfaceHolder.Callback, + SeekBar.OnSeekBarChangeListener { + private Bitmap mBitmapIn; + private Bitmap mBitmapOut; + private Bitmap mBitmapScratch; + private ScriptC_threshold mScript; + private ScriptC_vertical_blur mScriptVBlur; + private ScriptC_horizontal_blur mScriptHBlur; + private int mRadius = 0; + private SeekBar mRadiusSeekBar; + + private float mInBlack = 0.0f; + private SeekBar mInBlackSeekBar; + private float mOutBlack = 0.0f; + private SeekBar mOutBlackSeekBar; + private float mInWhite = 255.0f; + private SeekBar mInWhiteSeekBar; + private float mOutWhite = 255.0f; + private SeekBar mOutWhiteSeekBar; + private float mGamma = 1.0f; + private SeekBar mGammaSeekBar; + + private float mSaturation = 1.0f; + private SeekBar mSaturationSeekBar; + + private TextView mBenchmarkResult; + + @SuppressWarnings({"FieldCanBeLocal"}) + private RenderScript mRS; + @SuppressWarnings({"FieldCanBeLocal"}) + private Type mPixelType; + @SuppressWarnings({"FieldCanBeLocal"}) + private Allocation mInPixelsAllocation; + @SuppressWarnings({"FieldCanBeLocal"}) + private Allocation mOutPixelsAllocation; + @SuppressWarnings({"FieldCanBeLocal"}) + private Allocation mScratchPixelsAllocation1; + private Allocation mScratchPixelsAllocation2; + + private SurfaceView mSurfaceView; + private ImageView mDisplayView; + + class FilterCallback extends RenderScript.RSMessageHandler { + private Runnable mAction = new Runnable() { + public void run() { + mDisplayView.invalidate(); + } + }; + + @Override + public void run() { + mSurfaceView.removeCallbacks(mAction); + mSurfaceView.post(mAction); + } + } + + int in[]; + int interm[]; + int out[]; + int MAX_RADIUS = 25; + // Store our coefficients here + float gaussian[]; + + private long javaFilter() { + final int width = mBitmapIn.getWidth(); + final int height = mBitmapIn.getHeight(); + final int count = width * height; + + if (in == null) { + in = new int[count]; + interm = new int[count]; + out = new int[count]; + gaussian = new float[MAX_RADIUS * 2 + 1]; + mBitmapIn.getPixels(in, 0, width, 0, 0, width, height); + } + + long t = java.lang.System.currentTimeMillis(); + + int w, h, r; + + float fRadius = (float)mRadius; + int radius = (int)mRadius; + + // 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 * fRadius + 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 / (float)(Math.sqrt( 2.0f * pi ) * sigma); + float coeff2 = - 1.0f / (2.0f * sigma * sigma); + float normalizeFactor = 0.0f; + float floatR = 0.0f; + for (r = -radius; r <= radius; r ++) { + floatR = (float)r; + gaussian[r + radius] = coeff1 * (float)Math.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; + } + + float blurredPixelR = 0.0f; + float blurredPixelG = 0.0f; + float blurredPixelB = 0.0f; + float blurredPixelA = 0.0f; + + for (h = 0; h < height; h ++) { + for (w = 0; w < width; w ++) { + + blurredPixelR = 0.0f; + blurredPixelG = 0.0f; + blurredPixelB = 0.0f; + blurredPixelA = 0.0f; + + for (r = -radius; r <= radius; r ++) { + // Stepping left and right away from the pixel + int validW = w + r; + // Clamp to zero and width max() isn't exposed for ints yet + if (validW < 0) { + validW = 0; + } + if (validW > width - 1) { + validW = width - 1; + } + + int input = in[h*width + validW]; + + int R = ((input >> 24) & 0xff); + int G = ((input >> 16) & 0xff); + int B = ((input >> 8) & 0xff); + int A = (input & 0xff); + + float weight = gaussian[r + radius]; + + blurredPixelR += (float)(R)*weight; + blurredPixelG += (float)(G)*weight; + blurredPixelB += (float)(B)*weight; + blurredPixelA += (float)(A)*weight; + } + + int R = (int)blurredPixelR; + int G = (int)blurredPixelG; + int B = (int)blurredPixelB; + int A = (int)blurredPixelA; + + interm[h*width + w] = (R << 24) | (G << 16) | (B << 8) | (A); + } + } + + for (h = 0; h < height; h ++) { + for (w = 0; w < width; w ++) { + + blurredPixelR = 0.0f; + blurredPixelG = 0.0f; + blurredPixelB = 0.0f; + blurredPixelA = 0.0f; + for (r = -radius; r <= radius; r ++) { + int validH = h + r; + // Clamp to zero and width + if (validH < 0) { + validH = 0; + } + if (validH > height - 1) { + validH = height - 1; + } + + int input = interm[validH*width + w]; + + int R = ((input >> 24) & 0xff); + int G = ((input >> 16) & 0xff); + int B = ((input >> 8) & 0xff); + int A = (input & 0xff); + + float weight = gaussian[r + radius]; + + blurredPixelR += (float)(R)*weight; + blurredPixelG += (float)(G)*weight; + blurredPixelB += (float)(B)*weight; + blurredPixelA += (float)(A)*weight; + } + + int R = (int)blurredPixelR; + int G = (int)blurredPixelG; + int B = (int)blurredPixelB; + int A = (int)blurredPixelA; + + out[h*width + w] = (R << 24) | (G << 16) | (B << 8) | (A); + } + } + + t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Java frame time ms " + t); + mBitmapOut.setPixels(out, 0, width, 0, 0, width, height); + return t; + } + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + + if (seekBar == mRadiusSeekBar) { + float fRadius = progress / 100.0f; + fRadius *= (float)(MAX_RADIUS); + mRadius = (int)fRadius; + + mScript.set_radius(mRadius); + } else if (seekBar == mInBlackSeekBar) { + mInBlack = (float)progress; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mOutBlackSeekBar) { + mOutBlack = (float)progress; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mInWhiteSeekBar) { + mInWhite = (float)progress + 127.0f; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mOutWhiteSeekBar) { + mOutWhite = (float)progress + 127.0f; + mScriptVBlur.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; + mScriptVBlur.invoke_setGamma(mGamma); + } else if (seekBar == mSaturationSeekBar) { + mSaturation = (float)progress / 50.0f; + mScriptVBlur.invoke_setSaturation(mSaturation); + } + + long t = java.lang.System.currentTimeMillis(); + if (true) { + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + } else { + javaFilter(); + mDisplayView.invalidate(); + } + + t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Renderscript frame time core ms " + t); + } + } + + public void onStartTrackingTouch(SeekBar seekBar) { + } + + public void onStopTrackingTouch(SeekBar seekBar) { + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + mBitmapIn = loadBitmap(R.drawable.data); + mBitmapOut = loadBitmap(R.drawable.data); + mBitmapScratch = loadBitmap(R.drawable.data); + + mSurfaceView = (SurfaceView) findViewById(R.id.surface); + mSurfaceView.getHolder().addCallback(this); + + mDisplayView = (ImageView) findViewById(R.id.display); + mDisplayView.setImageBitmap(mBitmapOut); + + mRadiusSeekBar = (SeekBar) findViewById(R.id.radius); + mRadiusSeekBar.setOnSeekBarChangeListener(this); + + mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack); + mInBlackSeekBar.setOnSeekBarChangeListener(this); + mInBlackSeekBar.setMax(128); + mInBlackSeekBar.setProgress(0); + mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack); + mOutBlackSeekBar.setOnSeekBarChangeListener(this); + mOutBlackSeekBar.setMax(128); + mOutBlackSeekBar.setProgress(0); + + mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite); + mInWhiteSeekBar.setOnSeekBarChangeListener(this); + mInWhiteSeekBar.setMax(128); + mInWhiteSeekBar.setProgress(128); + mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite); + mOutWhiteSeekBar.setOnSeekBarChangeListener(this); + mOutWhiteSeekBar.setMax(128); + mOutWhiteSeekBar.setProgress(128); + + mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma); + mGammaSeekBar.setOnSeekBarChangeListener(this); + mGammaSeekBar.setMax(150); + mGammaSeekBar.setProgress(100); + + mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation); + mSaturationSeekBar.setOnSeekBarChangeListener(this); + mSaturationSeekBar.setProgress(50); + + mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); + mBenchmarkResult.setText("Result: not run"); + } + + public void surfaceCreated(SurfaceHolder holder) { + createScript(); + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } + + public void surfaceDestroyed(SurfaceHolder holder) { + } + + private void createScript() { + mRS = RenderScript.create(this); + mRS.setMessageHandler(new FilterCallback()); + + mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + + Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS)); + tb.setX(mBitmapIn.getWidth()); + tb.setY(mBitmapIn.getHeight()); + mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create()); + mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create()); + + mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur); + mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur); + + mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold); + mScript.set_width(mBitmapIn.getWidth()); + mScript.set_height(mBitmapIn.getHeight()); + mScript.set_radius(mRadius); + + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + mScriptVBlur.invoke_setGamma(mGamma); + mScriptVBlur.invoke_setSaturation(mSaturation); + + mScript.bind_InPixel(mInPixelsAllocation); + mScript.bind_OutPixel(mOutPixelsAllocation); + mScript.bind_ScratchPixel1(mScratchPixelsAllocation1); + mScript.bind_ScratchPixel2(mScratchPixelsAllocation2); + + mScript.set_vBlurScript(mScriptVBlur); + mScript.set_hBlurScript(mScriptHBlur); + } + + private Bitmap loadBitmap(int resource) { + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options)); + } + + private static Bitmap copyBitmap(Bitmap source) { + Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig()); + Canvas c = new Canvas(b); + c.drawBitmap(source, 0, 0, null); + source.recycle(); + return b; + } + + // button hook + public void benchmark(View v) { + android.util.Log.v("Img", "Benchmarking"); + int oldRadius = mRadius; + mRadius = MAX_RADIUS; + mScript.set_radius(mRadius); + + long t = java.lang.System.currentTimeMillis(); + + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + + t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Renderscript frame time core ms " + t); + + //long javaTime = javaFilter(); + //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms"); + mBenchmarkResult.setText("Result: " + t + " ms"); + + mRadius = oldRadius; + mScript.set_radius(mRadius); + + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + } +} diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs new file mode 100644 index 0000000..652ffd7 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs @@ -0,0 +1,30 @@ +#pragma version(1) + +#include "ip.rsh" + +void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { + float4 *output = (float4 *)v_out; + const FilterStruct *fs = (const FilterStruct *)usrData; + const float4 *input = (const float4 *)rsGetElementAt(fs->ain, 0, y); + + float3 blurredPixel = 0; + const float *gPtr = fs->gaussian; + if ((x > fs->radius) && (x < (fs->width - fs->radius))) { + const float4 *i = input + (x - fs->radius); + for (int r = -fs->radius; r <= fs->radius; r ++) { + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + i++; + } + } else { + for (int r = -fs->radius; r <= fs->radius; r ++) { + // Stepping left and right away from the pixel + int validW = rsClamp(x + r, (uint)0, (uint)(fs->width - 1)); + blurredPixel += input[validW].xyz * gPtr[0]; + gPtr++; + } + } + + output->xyz = blurredPixel; +} + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh new file mode 100644 index 0000000..1d7a719 --- /dev/null +++ b/tests/RenderScriptTests/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 FilterStruct_s { + rs_allocation ain; + + float *gaussian; //[MAX_RADIUS * 2 + 1]; + int height; + int width; + int radius; + +} FilterStruct; + + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs new file mode 100644 index 0000000..f2f9a36 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs @@ -0,0 +1,93 @@ +#pragma version(1) + +#include "ip.rsh" + +int height; +int width; +int radius; + +uchar4 * InPixel; +uchar4 * OutPixel; +float4 * ScratchPixel1; +float4 * ScratchPixel2; + +rs_script vBlurScript; +rs_script hBlurScript; + +const int CMD_FINISHED = 1; + +// 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 copyInput() { + rs_allocation ain; + rsSetObject(&ain,rsGetAllocation(InPixel)); + uint32_t dimx = rsAllocationGetDimX(ain); + uint32_t dimy = rsAllocationGetDimY(ain); + for (uint32_t y = 0; y < dimy; y++) { + for (uint32_t x = 0; x < dimx; x++) { + ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]); + } + } +} + +void filter() { + copyInput(); + computeGaussianWeights(); + + FilterStruct fs; + fs.gaussian = gaussian; + fs.width = width; + fs.height = height; + fs.radius = radius; + + fs.ain = rsGetAllocation(ScratchPixel1); + rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs); + + fs.ain = rsGetAllocation(ScratchPixel2); + rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs); + rsSendToClientBlocking(CMD_FINISHED); +} + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs new file mode 100644 index 0000000..bd4ae4e --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs @@ -0,0 +1,93 @@ +#pragma version(1) + +#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; + +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; +} + +//sliao +extern uchar3 __attribute__((overloadable)) convert2uchar3(float3 xyz); + +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 float4 *input = (const float4 *)rsGetElementAt(fs->ain, x, 0); + + float3 blurredPixel = 0; + const float *gPtr = fs->gaussian; + if ((y > fs->radius) && (y < (fs->height - fs->radius))) { + const float4 *i = input + ((y - fs->radius) * fs->width); + for (int r = -fs->radius; r <= fs->radius; r ++) { + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + i += fs->width; + } + } else { + for (int r = -fs->radius; r <= fs->radius; r ++) { + int validH = rsClamp(y + r, (uint)0, (uint)(fs->height - 1)); + const float4 *i = input + validH * fs->width; + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + } + } + + float3 temp = rsMatrixMultiply(&colorMat, blurredPixel); + temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB; + if (gamma.x != 1.0f) + temp = pow(temp, (float3)gamma); + temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f); + + output->xyz = convert_uchar3(temp); + //output->w = input->w; +} + |