diff options
Diffstat (limited to 'libs/rs/java')
25 files changed, 1671 insertions, 383 deletions
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java index 7d04502..93438a0 100644 --- a/libs/rs/java/Film/src/com/android/film/FilmRS.java +++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java @@ -213,14 +213,9 @@ public class FilmRS { Log.e("rs", "Done loading named"); - mStripPositionType = Type.createFromClass(mRS, StripPosition.class, 1); - ScriptC.Builder sb = new ScriptC.Builder(mRS); sb.setScript(mRes, R.raw.filmstrip); - sb.setRoot(true); - sb.setType(mStripPositionType, "Pos", 1); mScriptStrip = sb.create(); - mScriptStrip.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); mAllocPos = Allocation.createTyped(mRS, mStripPositionType); diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c deleted file mode 100644 index 73b819b..0000000 --- a/libs/rs/java/Fountain/res/raw/fountain.c +++ /dev/null @@ -1,52 +0,0 @@ -// Fountain test script -#pragma version(1) - -int newPart = 0; - -int main(int launchID) { - int ct; - int count = Control->count; - int rate = Control->rate; - float height = getHeight(); - struct point_s * p = (struct point_s *)point; - - if (rate) { - float rMax = ((float)rate) * 0.005f; - int x = Control->x; - int y = Control->y; - int color = ((int)(Control->r * 255.f)) | - ((int)(Control->g * 255.f)) << 8 | - ((int)(Control->b * 255.f)) << 16 | - (0xf0 << 24); - struct point_s * np = &p[newPart]; - - while (rate--) { - vec2Rand((float *)&np->delta.x, rMax); - np->position.x = x; - np->position.y = y; - np->color = color; - newPart++; - np++; - if (newPart >= count) { - newPart = 0; - np = &p[newPart]; - } - } - } - - for (ct=0; ct < count; ct++) { - float dy = p->delta.y + 0.15f; - float posy = p->position.y + dy; - if ((posy > height) && (dy > 0)) { - dy *= -0.3f; - } - p->delta.y = dy; - p->position.x += p->delta.x; - p->position.y = posy; - p++; - } - - uploadToBufferObject(NAMED_PartBuffer); - drawSimpleMesh(NAMED_PartMesh); - return 1; -} diff --git a/libs/rs/java/Fountain/res/raw/fountain.rs b/libs/rs/java/Fountain/res/raw/fountain.rs new file mode 100644 index 0000000..7573398 --- /dev/null +++ b/libs/rs/java/Fountain/res/raw/fountain.rs @@ -0,0 +1,77 @@ +// Fountain test script +#pragma version(1) + +#include "../../../../scriptc/rs_types.rsh" +#include "../../../../scriptc/rs_math.rsh" +#include "../../../../scriptc/rs_graphics.rsh" + +static int newPart = 0; + +float4 partColor; +rs_mesh partMesh; + +typedef struct __attribute__((packed, aligned(4))) Point_s { + float2 delta; + float2 position; + uchar4 color; +} Point_t; +Point_t *point; + +#pragma rs export_var(point, partColor, partMesh) + +int root() { + rsgClearColor(0.f, 0.f, 0.f, 1.f); + float height = rsgGetHeight(); + rs_allocation alloc = rsGetAllocation(point); + int size = rsAllocationGetDimX(alloc); + + Point_t * p = point; + for (int ct=0; ct < size; ct++) { + p->delta.y += 0.15f; + p->position += p->delta; + if ((p->position.y > height) && (p->delta.y > 0)) { + p->delta.y *= -0.3f; + } + p++; + } + + rsgUploadToBufferObject(alloc); + rsgDrawSimpleMesh(partMesh); + return 1; +} + +#pragma rs export_func(addParticles) + +void addParticles(int rate, int x, int y) +{ + //rsDebug("partColor", partColor); + //rsDebug("partColor x", partColor.x); + //rsDebug("partColor y", partColor.y); + //rsDebug("partColor z", partColor.z); + //rsDebug("partColor w", partColor.w); + + float rMax = ((float)rate) * 0.005f; + int size = rsAllocationGetDimX(rsGetAllocation(point)); + + uchar4 c = rsPackColorTo8888(partColor.x, partColor.y, partColor.z); + + //rsDebug("color ", ((int *)&c)[0]); + Point_t * np = &point[newPart]; + + float2 p = {x, y}; + while (rate--) { + float angle = rsRand(3.14f * 2.f); + float len = rsRand(rMax); + np->delta.x = len * sin(angle); + np->delta.y = len * cos(angle); + np->position = p; + np->color = c; + newPart++; + np++; + if (newPart >= size) { + newPart = 0; + np = &point[newPart]; + } + } +} + diff --git a/libs/rs/java/Fountain/res/raw/fountain2.rs b/libs/rs/java/Fountain/res/raw/fountain2.rs deleted file mode 100644 index 3301140..0000000 --- a/libs/rs/java/Fountain/res/raw/fountain2.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Fountain test script -#pragma version(1) - -#include "rs_types.rsh" -#include "rs_math.rsh" -#include "rs_graphics.rsh" - -static int newPart = 0; - -typedef struct Control_s { - int x, y; - int rate; - int count; - float r, g, b; - rs_allocation partBuffer; - rs_mesh partMesh; -} Control_t; -Control_t *Control; - -typedef struct Point_s{ - float2 delta; - float2 position; - unsigned int color; -} Point_t; -Point_t *point; - -int main(int launchID) { - int ct; - int count = Control->count; - int rate = Control->rate; - float height = getHeight(); - Point_t * p = point; - - if (rate) { - float rMax = ((float)rate) * 0.005f; - int x = Control->x; - int y = Control->y; - int color = ((int)(Control->r * 255.f)) | - ((int)(Control->g * 255.f)) << 8 | - ((int)(Control->b * 255.f)) << 16 | - (0xf0 << 24); - Point_t * np = &p[newPart]; - - while (rate--) { - np->delta = vec2Rand(rMax); - np->position.x = x; - np->position.y = y; - np->color = color; - newPart++; - np++; - if (newPart >= count) { - newPart = 0; - np = &p[newPart]; - } - } - } - - for (ct=0; ct < count; ct++) { - float dy = p->delta.y + 0.15f; - float posy = p->position.y + dy; - if ((posy > height) && (dy > 0)) { - dy *= -0.3f; - } - p->delta.y = dy; - p->position.x += p->delta.x; - p->position.y = posy; - p++; - } - - uploadToBufferObject(Control->partBuffer); - drawSimpleMesh(Control->partMesh); - return 1; -} diff --git a/libs/rs/java/Fountain/res/raw/fountain_bc.bc b/libs/rs/java/Fountain/res/raw/fountain_bc.bc Binary files differnew file mode 100644 index 0000000..b01098b --- /dev/null +++ b/libs/rs/java/Fountain/res/raw/fountain_bc.bc diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java index 9356579..5433597 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java @@ -24,92 +24,48 @@ import android.util.Log; public class FountainRS { public static final int PART_COUNT = 20000; - static class SomeData { - public int x; - public int y; - public int rate; - public int count; - public float r; - public float g; - public float b; - } - public FountainRS() { } + private Resources mRes; + private RenderScriptGL mRS; + private ScriptC_Fountain mScript; public void init(RenderScriptGL rs, Resources res, int width, int height) { mRS = rs; mRes = res; - initRS(); - } - - public void newTouchPosition(int x, int y, int rate) { - if (mSD.rate == 0) { - mSD.r = ((x & 0x1) != 0) ? 0.f : 1.f; - mSD.g = ((x & 0x2) != 0) ? 0.f : 1.f; - mSD.b = ((x & 0x4) != 0) ? 0.f : 1.f; - if ((mSD.r + mSD.g + mSD.b) < 0.9f) { - mSD.r = 0.8f; - mSD.g = 0.5f; - mSD.b = 1.f; - } - } - mSD.rate = rate; - mSD.x = x; - mSD.y = y; - mIntAlloc.data(mSD); - } - - - ///////////////////////////////////////// - - private Resources mRes; - - private RenderScriptGL mRS; - private Allocation mIntAlloc; - private SimpleMesh mSM; - private SomeData mSD; - private Type mSDType; - - private void initRS() { - mSD = new SomeData(); - mSDType = Type.createFromClass(mRS, SomeData.class, 1, "SomeData"); - mIntAlloc = Allocation.createTyped(mRS, mSDType); - mSD.count = PART_COUNT; - mIntAlloc.data(mSD); - - Element.Builder eb = new Element.Builder(mRS); - eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "delta"); - eb.add(Element.createAttrib(mRS, Element.DataType.FLOAT_32, Element.DataKind.POSITION, 2), "position"); - eb.add(Element.createAttrib(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.COLOR, 4), "color"); - Element primElement = eb.create(); + ScriptField_Point_s points = new ScriptField_Point_s(mRS, PART_COUNT); SimpleMesh.Builder smb = new SimpleMesh.Builder(mRS); - int vtxSlot = smb.addVertexType(primElement, PART_COUNT); + int vtxSlot = smb.addVertexType(points.getType()); smb.setPrimitive(Primitive.POINT); - mSM = smb.create(); - mSM.setName("PartMesh"); + SimpleMesh sm = smb.create(); + sm.bindVertexAllocation(points.getAllocation(), vtxSlot); - Allocation partAlloc = mSM.createVertexAllocation(vtxSlot); - partAlloc.setName("PartBuffer"); - mSM.bindVertexAllocation(partAlloc, 0); + mScript = new ScriptC_Fountain(mRS, mRes, true); + mScript.set_partMesh(sm); + mScript.bind_point(points); + mRS.contextBindRootScript(mScript); + } - // All setup of named objects should be done by this point - // because we are about to compile the script. - ScriptC.Builder sb = new ScriptC.Builder(mRS); - sb.setScript(mRes, R.raw.fountain); - sb.setRoot(true); - sb.setType(mSDType, "Control", 0); - sb.setType(mSM.getVertexType(0), "point", 1); - Script script = sb.create(); - script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); + Float4 tmpColor = new Float4(); + boolean holdingColor = false; + java.util.Random mRand = new java.util.Random(); + public void newTouchPosition(int x, int y, int rate) { + if (rate > 0) { + if (!holdingColor) { + tmpColor.x = mRand.nextFloat() * 0.5f + 0.5f; + tmpColor.y = mRand.nextFloat(); + tmpColor.z = mRand.nextFloat(); + mScript.set_partColor(tmpColor); + } + mScript.invoke_addParticles(rate, x, y); + holdingColor = true; + } else { + holdingColor = false; + } - script.bindAllocation(mIntAlloc, 0); - script.bindAllocation(partAlloc, 1); - mRS.contextBindRootScript(script); } - } diff --git a/libs/rs/java/Fountain/src/com/android/fountain/ScriptC_Fountain.java b/libs/rs/java/Fountain/src/com/android/fountain/ScriptC_Fountain.java new file mode 100644 index 0000000..f6bef27 --- /dev/null +++ b/libs/rs/java/Fountain/src/com/android/fountain/ScriptC_Fountain.java @@ -0,0 +1,77 @@ +/* + * 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.fountain; + +import android.renderscript.*; +import android.content.res.Resources; +import android.util.Log; + +public class ScriptC_Fountain extends ScriptC { + // Constructor + public ScriptC_Fountain(RenderScript rs, Resources resources, boolean isRoot) { + super(rs, resources, R.raw.fountain_bc, isRoot); + } + + private final static int mExportVarIdx_partColor = 0; + private Float4 mExportVar_partColor; + public void set_partColor(Float4 v) { + mExportVar_partColor = v; + FieldPacker fp = new FieldPacker(16); + fp.addF32(v); + setVar(mExportVarIdx_partColor, fp); + } + + public Float4 get_partColor() { + return mExportVar_partColor; + } + + private final static int mExportVarIdx_partMesh = 1; + private SimpleMesh mExportVar_partMesh; + public void set_partMesh(SimpleMesh v) { + mExportVar_partMesh = v; + int id = 0; + if (v != null) id = v.getID(); + setVar(mExportVarIdx_partMesh, id); + } + + public SimpleMesh get_partMesh() { + return mExportVar_partMesh; + } + + private final static int mExportVarIdx_point = 2; + private ScriptField_Point_s mExportVar_point; + public void bind_point(ScriptField_Point_s v) { + mExportVar_point = v; + if(v == null) bindAllocation(null, mExportVarIdx_point); + else bindAllocation(v.getAllocation(), mExportVarIdx_point); + } + + public ScriptField_Point_s get_point() { + return mExportVar_point; + } + + private final static int mExportFuncIdx_addParticles = 0; + public void invoke_addParticles(int rate, int x, int y) { + FieldPacker addParticles_fp = new FieldPacker(12); + addParticles_fp.addI32(rate); + addParticles_fp.addI32(x); + addParticles_fp.addI32(y); + invokeV(mExportFuncIdx_addParticles, addParticles_fp); + } + +} + diff --git a/libs/rs/java/Fountain/src/com/android/fountain/ScriptField_Point_s.java b/libs/rs/java/Fountain/src/com/android/fountain/ScriptField_Point_s.java new file mode 100644 index 0000000..9697a4d --- /dev/null +++ b/libs/rs/java/Fountain/src/com/android/fountain/ScriptField_Point_s.java @@ -0,0 +1,79 @@ +/* + * 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.fountain; + +import android.renderscript.*; +import android.content.res.Resources; +import android.util.Log; + +public class ScriptField_Point_s extends android.renderscript.Script.FieldBase { + static public class Item { + public static final int sizeof = 20; + + Float2 delta; + Float2 position; + Short4 color; + + Item() { + delta = new Float2(); + position = new Float2(); + color = new Short4(); + } + + } + + private Item mItemArray[]; + private FieldPacker mIOBuffer; + public ScriptField_Point_s(RenderScript rs, int count) { + mItemArray = null; + mIOBuffer = null; + { + Element.Builder eb = new Element.Builder(rs); + eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 2), "delta"); + eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 2), "position"); + eb.add(Element.createVector(rs, Element.DataType.UNSIGNED_8, 4), "color"); + mElement = eb.create(); + } + + init(rs, count); + } + + private void copyToArray(Item i, int index) { + if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * mType.getX() /* count */); + mIOBuffer.reset(index * Item.sizeof); + mIOBuffer.addF32(i.delta); + mIOBuffer.addF32(i.position); + mIOBuffer.addU8(i.color); + } + + public void set(Item i, int index, boolean copyNow) { + if (mItemArray == null) mItemArray = new Item[mType.getX() /* count */]; + mItemArray[index] = i; + if (copyNow) { + copyToArray(i, index); + mAllocation.subData1D(index * Item.sizeof, Item.sizeof, mIOBuffer.getData()); + } + + } + + public void copyAll() { + for (int ct=0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct); + mAllocation.data(mIOBuffer.getData()); + } + +} + diff --git a/libs/rs/java/ImageProcessing/AndroidManifest.xml b/libs/rs/java/ImageProcessing/AndroidManifest.xml index b48d208..d6a2db4 100644 --- a/libs/rs/java/ImageProcessing/AndroidManifest.xml +++ b/libs/rs/java/ImageProcessing/AndroidManifest.xml @@ -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" /> diff --git a/libs/rs/java/ImageProcessing/res/layout/main.xml b/libs/rs/java/ImageProcessing/res/layout/main.xml index 6770c18..c6ec729 100644 --- a/libs/rs/java/ImageProcessing/res/layout/main.xml +++ b/libs/rs/java/ImageProcessing/res/layout/main.xml @@ -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/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/threshold" + 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>
\ No newline at end of file diff --git a/libs/rs/java/ImageProcessing/res/raw/threshold.rs b/libs/rs/java/ImageProcessing/res/raw/threshold.rs index 888f0cd..6af4012 100644 --- a/libs/rs/java/ImageProcessing/res/raw/threshold.rs +++ b/libs/rs/java/ImageProcessing/res/raw/threshold.rs @@ -1,62 +1,333 @@ -/* -// block of defines matching what RS will insert at runtime. -struct Params_s{ - int inHeight; - int inWidth; - int outHeight; - int outWidth; - float threshold; -}; -struct Params_s * Params; -struct InPixel_s{ - char a; - char b; - char g; - char r; -}; -struct InPixel_s * InPixel; -struct OutPixel_s{ - char a; - char b; - char g; - char r; -}; -struct OutPixel_s * OutPixel; -*/ - -struct color_s { - char b; - char g; - char r; - char a; -}; - -void main() { - int t = uptimeMillis(); - - struct color_s *in = (struct color_s *) InPixel; - struct color_s *out = (struct color_s *) OutPixel; - - int count = Params->inWidth * Params->inHeight; - int i; - float threshold = (Params->threshold * 255.f); - - for (i = 0; i < count; i++) { - float luminance = 0.2125f * in->r + - 0.7154f * in->g + - 0.0721f * in->b; - if (luminance > threshold) { - *out = *in; - } else { - *((int *)out) = *((int *)in) & 0xff000000; +#pragma version(1) + +#include "../../../../scriptc/rs_types.rsh" +#include "../../../../scriptc/rs_math.rsh" +#include "../../../../scriptc/rs_graphics.rsh" + +#define MAX_RADIUS 25 + +int height; +int width; +int radius; + +typedef struct c4u_s { + uint8_t r, g, b, a; +} c4u_t; + +c4u_t * InPixel; +c4u_t * OutPixel; +c4u_t * ScratchPixel; + +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; + + rsMatrixLoadIdentity((rs_matrix4x4 *)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(¤tPixel); + + 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; } + } + rsSendToClient(&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 ++) { - in++; - out++; + 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() { + RS_DEBUG(height); + RS_DEBUG(width); + RS_DEBUG(radius); + RS_DEBUG(inBlack); + RS_DEBUG(outBlack); + RS_DEBUG(inWhite); + RS_DEBUG(outWhite); + RS_DEBUG(gamma); + RS_DEBUG(saturation); + + computeColorMatrix(); + + if(radius == 0) { + processNoBlur(); + return; } - t= uptimeMillis() - t; - debugI32("Filter time", t); + computeGaussianWeights(); + + horizontalBlurLevels(); + verticalBlur(); + + int count = 0; + rsSendToClient(&count, 1, 4, 0); +} + +void filterBenchmark() { + + computeGaussianWeights(); - sendToClient(&count, 1, 4, 0); + horizontalBlur(); + verticalBlur(); + + int count = 0; + rsSendToClient(&count, 1, 4, 0); } + diff --git a/libs/rs/java/ImageProcessing/res/raw/threshold_bc.bc b/libs/rs/java/ImageProcessing/res/raw/threshold_bc.bc Binary files differnew file mode 100644 index 0000000..29eba2d --- /dev/null +++ b/libs/rs/java/ImageProcessing/res/raw/threshold_bc.bc diff --git a/libs/rs/java/ImageProcessing/res/values/strings.xml b/libs/rs/java/ImageProcessing/res/values/strings.xml new file mode 100644 index 0000000..cc5cc4d --- /dev/null +++ b/libs/rs/java/ImageProcessing/res/values/strings.xml @@ -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> 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 9ce53d8..5e36a78 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 @@ -31,53 +31,53 @@ 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 { - private Bitmap mBitmap; - private Params mParams; - private Script.Invokable mInvokable; - private int[] mInData; - private int[] mOutData; +public class ImageProcessingActivity extends Activity + implements SurfaceHolder.Callback, + SeekBar.OnSeekBarChangeListener { + private Bitmap mBitmapIn; + private Bitmap mBitmapOut; + private Bitmap mBitmapScratch; + private ScriptC_Threshold mScript; + 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 mParamsType; - @SuppressWarnings({"FieldCanBeLocal"}) - private Allocation mParamsAllocation; - @SuppressWarnings({"FieldCanBeLocal"}) private Type mPixelType; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mInPixelsAllocation; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mOutPixelsAllocation; + @SuppressWarnings({"FieldCanBeLocal"}) + private Allocation mScratchPixelsAllocation; private SurfaceView mSurfaceView; private ImageView mDisplayView; - static class Params { - public int inWidth; - public int outWidth; - public int inHeight; - public int outHeight; - - public float threshold; - } - - static class Pixel { - public byte a; - public byte r; - public byte g; - public byte b; - } - class FilterCallback extends RenderScript.RSMessage { private Runnable mAction = new Runnable() { public void run() { - mOutPixelsAllocation.readData(mOutData); - mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, - mParams.outWidth, mParams.outHeight); mDisplayView.invalidate(); } }; @@ -89,29 +89,218 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C } } - private void javaFilter() { + 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 count = mParams.inWidth * mParams.inHeight; - float threshold = mParams.threshold * 255.f; - - for (int i = 0; i < count; i++) { - final float r = (float)((mInData[i] >> 0) & 0xff); - final float g = (float)((mInData[i] >> 8) & 0xff); - final float b = (float)((mInData[i] >> 16) & 0xff); - - final float luminance = 0.2125f * r + - 0.7154f * g + - 0.0721f * b; - if (luminance > threshold) { - mOutData[i] = mInData[i]; - } else { - mOutData[i] = mInData[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); + } + } + + 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) { - android.util.Log.v("Img", "frame time ms " + t); + 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 @@ -119,45 +308,53 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C super.onCreate(savedInstanceState); setContentView(R.layout.main); - mBitmap = loadBitmap(R.drawable.data); + 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(mBitmap); - - ((SeekBar) findViewById(R.id.threshold)).setOnSeekBarChangeListener( - new SeekBar.OnSeekBarChangeListener() { - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - mParams.threshold = progress / 100.0f; - mParamsAllocation.data(mParams); - - if (true) { - mInvokable.execute(); - } else { - javaFilter(); - mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, - mParams.outWidth, mParams.outHeight); - mDisplayView.invalidate(); - } - } - } - - public void onStartTrackingTouch(SeekBar seekBar) { - } - - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); + 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("Benchmark no yet run"); } public void surfaceCreated(SurfaceHolder holder) { - mParams = createParams(); - mInvokable = createScript(); - - mInvokable.execute(); + createScript(); + mScript.invokable_Filter(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { @@ -166,54 +363,29 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C public void surfaceDestroyed(SurfaceHolder holder) { } - private Script.Invokable createScript() { + private void createScript() { mRS = RenderScript.create(); mRS.mMessageCallback = new FilterCallback(); - mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters"); - mParamsAllocation = Allocation.createTyped(mRS, mParamsType); - mParamsAllocation.data(mParams); - - final int pixelCount = mParams.inWidth * mParams.inHeight; - - mPixelType = Type.createFromClass(mRS, Pixel.class, 1, "Pixel"); - mInPixelsAllocation = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.SIGNED_32), - pixelCount); - mOutPixelsAllocation = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.SIGNED_32), - pixelCount); - - mInData = new int[pixelCount]; - mBitmap.getPixels(mInData, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight); - mInPixelsAllocation.data(mInData); - - mOutData = new int[pixelCount]; - mOutPixelsAllocation.data(mOutData); - - ScriptC.Builder sb = new ScriptC.Builder(mRS); - sb.setType(mParamsType, "Params", 0); - sb.setType(mPixelType, "InPixel", 1); - sb.setType(mPixelType, "OutPixel", 2); - sb.setType(true, 2); - Script.Invokable invokable = sb.addInvokable("main"); - sb.setScript(getResources(), R.raw.threshold); - //sb.setRoot(true); - - ScriptC script = sb.create(); - script.bindAllocation(mParamsAllocation, 0); - script.bindAllocation(mInPixelsAllocation, 1); - script.bindAllocation(mOutPixelsAllocation, 2); - - return invokable; - } - - private Params createParams() { - final Params params = new Params(); - params.inWidth = params.outWidth = mBitmap.getWidth(); - params.inHeight = params.outHeight = mBitmap.getHeight(); - params.threshold = 0.5f; - return params; + 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_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) { @@ -229,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(); + } } 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 new file mode 100644 index 0000000..dfed9e5 --- /dev/null +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ScriptC_Threshold.java @@ -0,0 +1,115 @@ + +package com.android.rs.image; + +import android.content.res.Resources; +import android.renderscript.*; +import android.util.Log; + +public class ScriptC_Threshold + extends android.renderscript.ScriptC +{ + private final static int mFieldIndex_height = 0; + private final static int mFieldIndex_width = 1; + 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); + } + + public void bind_InPixel(Allocation f) { + if (f != null) { + //if (f.getType().getElement() != Element.ATTRIB_COLOR_U8_4(mRS)) { + //throw new IllegalArgumentException("Element type mismatch."); + //} + } + bindAllocation(f, mFieldIndex_InPixel); + mField_InPixel = f; + } + public Allocation get_InPixel() { + return mField_InPixel; + } + + public void bind_OutPixel(Allocation f) { + if (f != null) { + //if (f.getType().getElement() != Element.ATTRIB_COLOR_U8_4(mRS)) { + //throw new IllegalArgumentException("Element type mismatch."); + //} + } + 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; + } + + public void set_height(int v) { + setVar(mFieldIndex_height, v); + } + + public void set_width(int v) { + setVar(mFieldIndex_width, v); + } + + public void set_radius(int v) { + setVar(mFieldIndex_radius, v); + } + + 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); + } +} + diff --git a/libs/rs/java/ModelViewer/Android.mk b/libs/rs/java/ModelViewer/Android.mk new file mode 100644 index 0000000..8bec6d6 --- /dev/null +++ b/libs/rs/java/ModelViewer/Android.mk @@ -0,0 +1,27 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) +#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript + +LOCAL_PACKAGE_NAME := ModelViewer + +include $(BUILD_PACKAGE) diff --git a/libs/rs/java/ModelViewer/AndroidManifest.xml b/libs/rs/java/ModelViewer/AndroidManifest.xml new file mode 100644 index 0000000..ebbe743 --- /dev/null +++ b/libs/rs/java/ModelViewer/AndroidManifest.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.modelviewer"> + <application android:label="ModelViewer"> + <activity android:name="ModelViewer" + android:screenOrientation="portrait" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/ModelViewer/res/drawable/robot.png b/libs/rs/java/ModelViewer/res/drawable/robot.png Binary files differnew file mode 100644 index 0000000..7c85e56 --- /dev/null +++ b/libs/rs/java/ModelViewer/res/drawable/robot.png diff --git a/libs/rs/java/ModelViewer/res/raw/modelviewer.rs b/libs/rs/java/ModelViewer/res/raw/modelviewer.rs new file mode 100644 index 0000000..6a98f90 --- /dev/null +++ b/libs/rs/java/ModelViewer/res/raw/modelviewer.rs @@ -0,0 +1,59 @@ +// 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. + +#pragma version(1) + +#include "../../../../scriptc/rs_types.rsh" +#include "../../../../scriptc/rs_math.rsh" +#include "../../../../scriptc/rs_graphics.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gTGrid; +rs_mesh gTestMesh; + +rs_program_store gPFSBackground; + +float gRotate; + +#pragma rs export_var(gPVBackground, gPFBackground, gTGrid, gTestMesh, gPFSBackground, gRotate) + +void init() { + gRotate = 0.0f; +} + +int root(int launchID) { + + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + + rsgBindProgramVertex(gPVBackground); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + // Position our model on the screen + rsMatrixTranslate(&matrix, 0.0f, -0.3f, 1.2f); + rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f); + rsMatrixRotate(&matrix, gRotate, 0.0f, 1.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgDrawSimpleMesh(gTestMesh); + + return 10; +} diff --git a/libs/rs/java/ModelViewer/res/raw/modelviewer_bc.bc b/libs/rs/java/ModelViewer/res/raw/modelviewer_bc.bc Binary files differnew file mode 100644 index 0000000..b02250b --- /dev/null +++ b/libs/rs/java/ModelViewer/res/raw/modelviewer_bc.bc diff --git a/libs/rs/java/ModelViewer/res/raw/robot.a3d b/libs/rs/java/ModelViewer/res/raw/robot.a3d Binary files differnew file mode 100644 index 0000000..c0c66ae --- /dev/null +++ b/libs/rs/java/ModelViewer/res/raw/robot.a3d diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java new file mode 100644 index 0000000..7491744 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package com.android.modelviewer; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class ModelViewer extends Activity { + + private ModelViewerView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new ModelViewerView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.onResume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.onPause(); + } + +} + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java new file mode 100644 index 0000000..dd52955 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java @@ -0,0 +1,156 @@ +/* + * 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + + +public class ModelViewerRS { + + private final int STATE_LAST_FOCUS = 1; + + int mWidth; + int mHeight; + int mRotation; + + public ModelViewerRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mRotation = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertex.MatrixAllocation mPVA; + + private Allocation mGridImage; + private Allocation mAllocPV; + + private SimpleMesh mMesh; + + private ScriptC_ModelViewer mScript; + + int mLastX; + int mLastY; + + public void touchEvent(int x, int y) { + int dx = mLastX - x; + if(Math.abs(dx) > 50 || Math.abs(dx) < 3) { + dx = 0; + } + + mRotation -= dx; + if(mRotation > 360) { + mRotation -= 360; + } + if(mRotation < 0) { + mRotation += 360; + } + + mScript.set_gRotate(-(float)mRotation); + + mLastX = x; + mLastY = y; + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnable(false); + b.setDepthMask(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMin(Sampler.Value.LINEAR); + bs.setMag(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.WRAP); + mSampler = bs.create(); + + ProgramFragment.Builder b = new ProgramFragment.Builder(mRS); + b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE, + ProgramFragment.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(mSampler, 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertex.MatrixAllocation(mRS); + mPVBackground.bindAllocation(mPVA); + mPVA.setupProjectionNormalized(mWidth, mHeight); + + mScript.set_gPVBackground(mPVBackground); + } + + private void loadImage() { + mGridImage = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.robot, Element.RGB_565(mRS), true); + mGridImage.uploadToTexture(1); + + mScript.set_gTGrid(mGridImage); + } + + private void initRS() { + + mScript = new ScriptC_ModelViewer(mRS, mRes, true); + + initPFS(); + initPF(); + initPV(); + + loadImage(); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if(entry == null || entry.getClassID() != FileA3D.ClassID.SIMPLE_MESH) { + Log.e("rs", "could not load model"); + } + else { + mMesh = (SimpleMesh)entry.getObject(); + mScript.set_gTestMesh(mMesh); + } + + mRS.contextBindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java new file mode 100644 index 0000000..ce76e1a --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class ModelViewerView extends RSSurfaceView { + + public ModelViewerView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private ModelViewerRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + mRS = createRenderScript(true); + mRS.contextSetSurface(w, h, holder.getSurface()); + mRender = new ModelViewerRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRS = null; + destroyRenderScript(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = true; + int act = ev.getAction(); + if (act == ev.ACTION_UP) { + ret = false; + } + + Log.v("rs", "Values " + (int)ev.getX() + " " + (int)ev.getY()); + mRender.touchEvent((int)ev.getX(), (int)ev.getY()); + return ret; + } +} + + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java new file mode 100644 index 0000000..f617c77 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java @@ -0,0 +1,42 @@ + +package com.android.modelviewer; + +import android.content.res.Resources; +import android.renderscript.*; +import android.util.Log; + + + +public class ScriptC_ModelViewer + extends android.renderscript.ScriptC +{ + public ScriptC_ModelViewer(RenderScript rs, Resources resources, boolean isRoot) { + super(rs, resources, R.raw.modelviewer_bc, isRoot); + } + + public void set_gPVBackground(ProgramVertex v) { + setVar(0, v.getID()); + } + + public void set_gPFBackground(ProgramFragment v) { + setVar(1, v.getID()); + } + + public void set_gTGrid(Allocation v) { + setVar(2, v.getID()); + } + + public void set_gTestMesh(SimpleMesh v) { + setVar(3, v.getID()); + } + + public void set_gPFSBackground(ProgramStore v) { + setVar(4, v.getID()); + } + + public void set_gRotate(float v) { + setVar(5, v); + } + +} + |
