Merge "Added benchmark mode. Added some image processing operations."

This commit is contained in:
Alex Sakhartchouk
2010-05-19 16:44:26 -07:00
committed by Android (Google) Code Review
7 changed files with 837 additions and 72 deletions

View File

@@ -6,7 +6,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:label="Image Processing">
<activity android:name="ImageProcessingActivity">
<activity android:name="ImageProcessingActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View File

@@ -25,9 +25,147 @@
android:id="@+id/display"
android:layout_width="320dip"
android:layout_height="266dip" />
<Button
android:layout_marginBottom="170dip"
android:layout_width="wrap_content"
android:layout_height="40dip"
android:text="@string/benchmark"
android:onClick="benchmark"
android:layout_gravity="bottom"/>
<TextView
android:id="@+id/benchmarkText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="100dip"
android:layout_marginBottom="175dip"
android:layout_gravity="bottom"
android:text="@string/saturation"/>
<SeekBar
android:id="@+id/inSaturation"
android:layout_marginBottom="140dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/inSaturationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="50dip"
android:layout_marginBottom="142dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/saturation"/>
<SeekBar
android:id="@+id/threshold"
android:id="@+id/inGamma"
android:layout_marginBottom="110dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/inGammaText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="50dip"
android:layout_marginBottom="112dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/gamma"/>
<SeekBar
android:id="@+id/outWhite"
android:layout_marginBottom="80dip"
android:layout_marginLeft="170dip"
android:layout_marginRight="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/outWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="220dip"
android:layout_marginBottom="82dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/out_white"/>
<SeekBar
android:id="@+id/inWhite"
android:layout_marginBottom="80dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="170dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/inWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="50dip"
android:layout_marginBottom="82dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/in_white"/>
<SeekBar
android:id="@+id/outBlack"
android:layout_marginBottom="50dip"
android:layout_marginLeft="170dip"
android:layout_marginRight="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/outBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="220dip"
android:layout_marginBottom="52dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/out_black"/>
<SeekBar
android:id="@+id/inBlack"
android:layout_marginBottom="50dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="170dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/inBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="50dip"
android:layout_marginBottom="52dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/in_black"/>
<SeekBar
android:id="@+id/radius"
android:layout_marginBottom="10dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
@@ -35,4 +173,15 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<TextView
android:id="@+id/blurText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginLeft="50dip"
android:layout_marginBottom="12dip"
android:textColor="#000"
android:layout_gravity="bottom"
android:text="@string/blur_description"/>
</merge>

View File

@@ -4,46 +4,331 @@
#include "../../../../scriptc/rs_math.rsh"
#include "../../../../scriptc/rs_graphics.rsh"
#define MAX_RADIUS 25
int height;
int width;
float threshold;
int radius;
typedef struct c4u_s {
char r, g, b, a;
uint8_t r, g, b, a;
} c4u_t;
//rs_color4u * InPixel;
//rs_color4u * OutPixel;
c4u_t * InPixel;
c4u_t * OutPixel;
c4u_t * ScratchPixel;
#pragma rs export_var(height, width, threshold, InPixel, OutPixel)
float inBlack;
float outBlack;
float inWhite;
float outWhite;
float gamma;
float saturation;
float inWMinInB;
float outWMinOutB;
#pragma rs export_var(height, width, radius, InPixel, OutPixel, ScratchPixel, inBlack, outBlack, inWhite, outWhite, gamma, saturation)
#pragma rs export_func(filter, processNoBlur, computeColorMatrix, computeGaussianWeights);
// Store our coefficients here
float gaussian[MAX_RADIUS * 2 + 1];
float colorMat[4][4];
void computeColorMatrix() {
// 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;
matrixLoadIdentity(colorMat);
colorMat[0][0] = oneMinusS * rWeight + saturation;
colorMat[0][1] = oneMinusS * rWeight;
colorMat[0][2] = oneMinusS * rWeight;
colorMat[1][0] = oneMinusS * gWeight;
colorMat[1][1] = oneMinusS * gWeight + saturation;
colorMat[1][2] = oneMinusS * gWeight;
colorMat[2][0] = oneMinusS * bWeight;
colorMat[2][1] = oneMinusS * bWeight;
colorMat[2][2] = oneMinusS * bWeight + saturation;
inWMinInB = inWhite - inBlack;
outWMinOutB = outWhite - outBlack;
}
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;
}
}
// This needs to be inline
void levelsSaturation(float4 *currentPixel) {
// Color matrix multiply
float tempX = colorMat[0][0] * currentPixel->x + colorMat[1][0] * currentPixel->y + colorMat[2][0] * currentPixel->z;
float tempY = colorMat[0][1] * currentPixel->x + colorMat[1][1] * currentPixel->y + colorMat[2][1] * currentPixel->z;
float tempZ = colorMat[0][2] * currentPixel->x + colorMat[1][2] * currentPixel->y + colorMat[2][2] * currentPixel->z;
currentPixel->x = tempX;
currentPixel->y = tempY;
currentPixel->z = tempZ;
// Clamp to 0..255
// Inline the code here to avoid funciton calls
currentPixel->x = currentPixel->x > 255.0f ? 255.0f : currentPixel->x;
currentPixel->y = currentPixel->y > 255.0f ? 255.0f : currentPixel->y;
currentPixel->z = currentPixel->z > 255.0f ? 255.0f : currentPixel->z;
currentPixel->x = currentPixel->x <= 0.0f ? 0.1f : currentPixel->x;
currentPixel->y = currentPixel->y <= 0.0f ? 0.1f : currentPixel->y;
currentPixel->z = currentPixel->z <= 0.0f ? 0.1f : currentPixel->z;
currentPixel->x = pow( (currentPixel->x - inBlack) / (inWMinInB), gamma) * (outWMinOutB) + outBlack;
currentPixel->y = pow( (currentPixel->y - inBlack) / (inWMinInB), gamma) * (outWMinOutB) + outBlack;
currentPixel->z = pow( (currentPixel->z - inBlack) / (inWMinInB), gamma) * (outWMinOutB) + outBlack;
currentPixel->x = currentPixel->x > 255.0f ? 255.0f : currentPixel->x;
currentPixel->y = currentPixel->y > 255.0f ? 255.0f : currentPixel->y;
currentPixel->z = currentPixel->z > 255.0f ? 255.0f : currentPixel->z;
currentPixel->x = currentPixel->x <= 0.0f ? 0.1f : currentPixel->x;
currentPixel->y = currentPixel->y <= 0.0f ? 0.1f : currentPixel->y;
currentPixel->z = currentPixel->z <= 0.0f ? 0.1f : currentPixel->z;
}
void processNoBlur() {
int w, h, r;
int count = 0;
float inWMinInB = inWhite - inBlack;
float outWMinOutB = outWhite - outBlack;
float4 currentPixel = 0;
for(h = 0; h < height; h ++) {
for(w = 0; w < width; w ++) {
c4u_t *input = InPixel + h*width + w;
currentPixel.x = (float)(input->r);
currentPixel.y = (float)(input->g);
currentPixel.z = (float)(input->b);
levelsSaturation(&currentPixel);
c4u_t *output = OutPixel + h*width + w;
output->r = (uint8_t)currentPixel.x;
output->g = (uint8_t)currentPixel.y;
output->b = (uint8_t)currentPixel.z;
output->a = input->a;
}
}
sendToClient(&count, 1, 4, 0);
}
void horizontalBlur() {
float4 blurredPixel = 0;
float4 currentPixel = 0;
// Horizontal blur
int w, h, r;
for(h = 0; h < height; h ++) {
for(w = 0; w < width; w ++) {
blurredPixel = 0;
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;
}
c4u_t *input = InPixel + h*width + validW;
float weight = gaussian[r + radius];
currentPixel.x = (float)(input->r);
currentPixel.y = (float)(input->g);
currentPixel.z = (float)(input->b);
//currentPixel.w = (float)(input->a);
blurredPixel += currentPixel*weight;
}
c4u_t *output = ScratchPixel + h*width + w;
output->r = (uint8_t)blurredPixel.x;
output->g = (uint8_t)blurredPixel.y;
output->b = (uint8_t)blurredPixel.z;
//output->a = (uint8_t)blurredPixel.w;
}
}
}
void horizontalBlurLevels() {
float4 blurredPixel = 0;
float4 currentPixel = 0;
// Horizontal blur
int w, h, r;
for(h = 0; h < height; h ++) {
for(w = 0; w < width; w ++) {
blurredPixel = 0;
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;
}
c4u_t *input = InPixel + h*width + validW;
float weight = gaussian[r + radius];
currentPixel.x = (float)(input->r);
currentPixel.y = (float)(input->g);
currentPixel.z = (float)(input->b);
//currentPixel.w = (float)(input->a);
blurredPixel += currentPixel*weight;
}
levelsSaturation(&blurredPixel);
c4u_t *output = ScratchPixel + h*width + w;
output->r = (uint8_t)blurredPixel.x;
output->g = (uint8_t)blurredPixel.y;
output->b = (uint8_t)blurredPixel.z;
//output->a = (uint8_t)blurredPixel.w;
}
}
}
void verticalBlur() {
float4 blurredPixel = 0;
float4 currentPixel = 0;
// Vertical blur
int w, h, r;
for(h = 0; h < height; h ++) {
for(w = 0; w < width; w ++) {
blurredPixel = 0;
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;
}
c4u_t *input = ScratchPixel + validH*width + w;
float weight = gaussian[r + radius];
currentPixel.x = (float)(input->r);
currentPixel.y = (float)(input->g);
currentPixel.z = (float)(input->b);
//currentPixel.w = (float)(input->a);
blurredPixel += currentPixel*weight;
}
c4u_t *output = OutPixel + h*width + w;
output->r = (uint8_t)blurredPixel.x;
output->g = (uint8_t)blurredPixel.y;
output->b = (uint8_t)blurredPixel.z;
//output->a = (uint8_t)blurredPixel.w;
}
}
}
void filter() {
debugP(0, (void *)height);
debugP(0, (void *)width);
debugP(0, (void *)((int)threshold));
debugP(0, (void *)InPixel);
debugP(0, (void *)OutPixel);
debugP(0, (void *)radius);
rs_color4u *in = (rs_color4u *)InPixel;
rs_color4u *out = (rs_color4u *)OutPixel;
//const rs_color4u mask = {0,0,0,0xff};
debugPf(10, inBlack);
debugPf(11, outBlack);
debugPf(12, inWhite);
debugPf(13, outWhite);
debugPf(14, gamma);
debugPf(15, saturation);
int count = width * height;
int tf = threshold * 255 * 255;
int masks[2] = {0xffffffff, 0xff000000};
computeColorMatrix();
while (count--) {
int luminance = 54 * in->x +
182 * in->y +
18 * in->z;
int idx = ((uint32_t)(luminance - tf)) >> 31;
*((int *)out) = *((int *)in) & masks[idx];
in++;
out++;
if(radius == 0) {
processNoBlur();
return;
}
computeGaussianWeights();
horizontalBlurLevels();
verticalBlur();
int count = 0;
sendToClient(&count, 1, 4, 0);
}
void filterBenchmark() {
computeGaussianWeights();
horizontalBlur();
verticalBlur();
int count = 0;
sendToClient(&count, 1, 4, 0);
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2008 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.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- General -->
<skip />
<!--slider label -->
<string name="blur_description">Blur Radius</string>
<string name="in_white">In White</string>
<string name="out_white">Out White</string>
<string name="in_black">In Black</string>
<string name="out_black">Out Black</string>
<string name="gamma">Gamma</string>
<string name="saturation">Saturation</string>
<string name="benchmark">Benchmark</string>
</resources>

View File

@@ -31,13 +31,35 @@ 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 {
public class ImageProcessingActivity extends Activity
implements SurfaceHolder.Callback,
SeekBar.OnSeekBarChangeListener {
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private Bitmap mBitmapScratch;
private ScriptC_Threshold mScript;
private float mThreshold = 0.5f;
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;
@@ -47,6 +69,8 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
private Allocation mInPixelsAllocation;
@SuppressWarnings({"FieldCanBeLocal"})
private Allocation mOutPixelsAllocation;
@SuppressWarnings({"FieldCanBeLocal"})
private Allocation mScratchPixelsAllocation;
private SurfaceView mSurfaceView;
private ImageView mDisplayView;
@@ -66,34 +90,217 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
}
int in[];
int interm[];
int out[];
private void javaFilter() {
final int w = mBitmapIn.getWidth();
final int h = mBitmapIn.getHeight();
final int count = w * h;
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];
mBitmapIn.getPixels(in, 0, w, 0, 0, w, h);
gaussian = new float[MAX_RADIUS * 2 + 1];
mBitmapIn.getPixels(in, 0, width, 0, 0, width, height);
}
int threshold = (int)(mThreshold * 255.f) * 255;
//long t = java.lang.System.currentTimeMillis();
long t = java.lang.System.currentTimeMillis();
for (int i = 0; i < count; i++) {
final int luminance = 54 * ((in[i] >> 0) & 0xff) +
182* ((in[i] >> 8) & 0xff) +
18 * ((in[i] >> 16) & 0xff);
if (luminance > threshold) {
out[i] = in[i];
} else {
out[i] = in[i] & 0xff000000;
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);
}
}
//t = java.lang.System.currentTimeMillis() - t;
//android.util.Log.v("Img", "frame time ms " + t);
mBitmapOut.setPixels(out, 0, w, 0, 0, w, h);
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;
mScript.set_inBlack(mInBlack);
}
else if(seekBar == mOutBlackSeekBar) {
mOutBlack = (float)progress;
mScript.set_outBlack(mOutBlack);
}
else if(seekBar == mInWhiteSeekBar) {
mInWhite = (float)progress + 127.0f;
mScript.set_inWhite(mInWhite);
}
else if(seekBar == mOutWhiteSeekBar) {
mOutWhite = (float)progress + 127.0f;
mScript.set_outWhite(mOutWhite);
}
else if(seekBar == mGammaSeekBar) {
mGamma = (float)progress/100.0f;
mGamma = Math.max(mGamma, 0.1f);
mGamma = 1.0f / mGamma;
mScript.set_gamma(mGamma);
}
else if(seekBar == mSaturationSeekBar) {
mSaturation = (float)progress / 50.0f;
mScript.set_saturation(mSaturation);
}
long t = java.lang.System.currentTimeMillis();
if (true) {
mScript.invokable_Filter();
} else {
javaFilter();
}
t = java.lang.System.currentTimeMillis() - t;
android.util.Log.v("Img", "Renderscript frame time core ms " + t);
mDisplayView.invalidate();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
@@ -103,6 +310,7 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
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);
@@ -110,31 +318,38 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
mDisplayView = (ImageView) findViewById(R.id.display);
mDisplayView.setImageBitmap(mBitmapOut);
((SeekBar) findViewById(R.id.threshold)).setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
mThreshold = progress / 100.0f;
mScript.set_threshold(mThreshold);
mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
mRadiusSeekBar.setOnSeekBarChangeListener(this);
long t = java.lang.System.currentTimeMillis();
if (true) {
mScript.invokable_Filter();
} else {
javaFilter();
mDisplayView.invalidate();
}
t = java.lang.System.currentTimeMillis() - t;
android.util.Log.v("Img", "frame time core ms " + t);
}
}
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);
public void onStartTrackingTouch(SeekBar seekBar) {
}
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);
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
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("Benchmark no yet run");
}
public void surfaceCreated(SurfaceHolder holder) {
@@ -154,13 +369,23 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
mInPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapIn);
mOutPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapOut);
mScratchPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapScratch);
mScript = new ScriptC_Threshold(mRS, getResources(), false);
mScript.set_width(mBitmapIn.getWidth());
mScript.set_height(mBitmapIn.getHeight());
mScript.set_threshold(mThreshold);
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);
mScript.bind_InPixel(mInPixelsAllocation);
mScript.bind_OutPixel(mOutPixelsAllocation);
mScript.bind_ScratchPixel(mScratchPixelsAllocation);
}
private Bitmap loadBitmap(int resource) {
@@ -176,4 +401,28 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C
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.invokable_FilterBenchmark();
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");
mRadius = oldRadius;
mScript.set_radius(mRadius);
mScript.invokable_Filter();
}
}

View File

@@ -10,12 +10,23 @@ public class ScriptC_Threshold
{
private final static int mFieldIndex_height = 0;
private final static int mFieldIndex_width = 1;
private final static int mFieldIndex_threshold = 2;
private final static int mFieldIndex_radius = 2;
private final static int mFieldIndex_InPixel = 3;
private final static int mFieldIndex_OutPixel = 4;
private final static int mFieldIndex_ScratchPixel = 5;
private final static int mFieldIndex_inBlack = 6;
private final static int mFieldIndex_outBlack = 7;
private final static int mFieldIndex_inWhite = 8;
private final static int mFieldIndex_outWhite = 9;
private final static int mFieldIndex_gamma = 10;
private final static int mFieldIndex_saturation = 11;
private final static int mFieldIndex_hue = 12;
private Allocation mField_InPixel;
private Allocation mField_OutPixel;
private Allocation mField_ScratchPixel;
public ScriptC_Threshold(RenderScript rs, Resources resources, boolean isRoot) {
super(rs, resources, R.raw.threshold_bc, isRoot);
@@ -43,6 +54,15 @@ public class ScriptC_Threshold
bindAllocation(f, mFieldIndex_OutPixel);
mField_OutPixel = f;
}
public void bind_ScratchPixel(Allocation f) {
if (f != null) {
//if (f.getType().getElement() != Element.ATTRIB_COLOR_U8_4(mRS)) {
//throw new IllegalArgumentException("Element type mismatch.");
//}
}
bindAllocation(f, mFieldIndex_ScratchPixel);
mField_ScratchPixel = f;
}
public Allocation get_OutPixel() {
return mField_OutPixel;
}
@@ -55,13 +75,41 @@ public class ScriptC_Threshold
setVar(mFieldIndex_width, v);
}
public void set_threshold(float v) {
setVar(mFieldIndex_threshold, v);
public void set_radius(int v) {
setVar(mFieldIndex_radius, v);
}
private final static int mInvokableIndex_Filter = 0;
public void set_inBlack(float v) {
setVar(mFieldIndex_inBlack, v);
}
public void set_outBlack(float v) {
setVar(mFieldIndex_outBlack, v);
}
public void set_inWhite(float v) {
setVar(mFieldIndex_inWhite, v);
}
public void set_outWhite(float v) {
setVar(mFieldIndex_outWhite, v);
}
public void set_gamma(float v) {
setVar(mFieldIndex_gamma, v);
}
public void set_saturation(float v) {
setVar(mFieldIndex_saturation, v);
}
public void set_hue(float v) {
setVar(mFieldIndex_hue, v);
}
private final static int mInvokableIndex_Filter = 2;
public void invokable_Filter() {
invokeData(mInvokableIndex_Filter);
}
private final static int mInvokableIndex_FilterBenchmark = 3;
public void invokable_FilterBenchmark() {
invokeData(mInvokableIndex_FilterBenchmark);
}
}