1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.rs.image; 18 19 import android.app.Activity; 20 import android.os.Bundle; 21 import android.graphics.BitmapFactory; 22 import android.graphics.Bitmap; 23 import android.graphics.Canvas; 24 import android.renderscript.ScriptC; 25 import android.renderscript.RenderScript; 26 import android.renderscript.Type; 27 import android.renderscript.Allocation; 28 import android.renderscript.Element; 29 import android.renderscript.Script; 30 import android.view.SurfaceView; 31 import android.view.SurfaceHolder; 32 import android.widget.ImageView; 33 import android.widget.SeekBar; 34 import android.widget.TextView; 35 import android.view.View; 36 import android.util.Log; 37 import java.lang.Math; 38 39 public class ImageProcessingActivity extends Activity 40 implements SurfaceHolder.Callback, 41 SeekBar.OnSeekBarChangeListener { 42 private final String TAG = "Img"; 43 private Bitmap mBitmapIn; 44 private Bitmap mBitmapOut; 45 private ScriptC_threshold mScript; 46 private ScriptC_vertical_blur mScriptVBlur; 47 private ScriptC_horizontal_blur mScriptHBlur; 48 private int mRadius = 0; 49 private SeekBar mRadiusSeekBar; 50 51 private float mInBlack = 0.0f; 52 private SeekBar mInBlackSeekBar; 53 private float mOutBlack = 0.0f; 54 private SeekBar mOutBlackSeekBar; 55 private float mInWhite = 255.0f; 56 private SeekBar mInWhiteSeekBar; 57 private float mOutWhite = 255.0f; 58 private SeekBar mOutWhiteSeekBar; 59 private float mGamma = 1.0f; 60 private SeekBar mGammaSeekBar; 61 62 private float mSaturation = 1.0f; 63 private SeekBar mSaturationSeekBar; 64 65 private TextView mBenchmarkResult; 66 67 @SuppressWarnings({"FieldCanBeLocal"}) 68 private RenderScript mRS; 69 @SuppressWarnings({"FieldCanBeLocal"}) 70 private Type mPixelType; 71 @SuppressWarnings({"FieldCanBeLocal"}) 72 private Allocation mInPixelsAllocation; 73 @SuppressWarnings({"FieldCanBeLocal"}) 74 private Allocation mOutPixelsAllocation; 75 @SuppressWarnings({"FieldCanBeLocal"}) 76 private Allocation mScratchPixelsAllocation1; 77 private Allocation mScratchPixelsAllocation2; 78 79 private SurfaceView mSurfaceView; 80 private ImageView mDisplayView; 81 82 private boolean mIsProcessing; 83 84 class FilterCallback extends RenderScript.RSMessageHandler { 85 private Runnable mAction = new Runnable() { 86 public void run() { 87 88 synchronized (mDisplayView) { 89 mIsProcessing = false; 90 } 91 92 mOutPixelsAllocation.copyTo(mBitmapOut); 93 mDisplayView.invalidate(); 94 } 95 }; 96 97 @Override 98 public void run() { 99 mSurfaceView.removeCallbacks(mAction); 100 mSurfaceView.post(mAction); 101 } 102 } 103 104 int in[]; 105 int interm[]; 106 int out[]; 107 int MAX_RADIUS = 25; 108 // Store our coefficients here 109 float gaussian[]; 110 111 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 112 if (fromUser) { 113 114 if (seekBar == mRadiusSeekBar) { 115 float fRadius = progress / 100.0f; 116 fRadius *= (float)(MAX_RADIUS); 117 mRadius = (int)fRadius; 118 119 mScript.set_radius(mRadius); 120 } else if (seekBar == mInBlackSeekBar) { 121 mInBlack = (float)progress; 122 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); 123 } else if (seekBar == mOutBlackSeekBar) { 124 mOutBlack = (float)progress; 125 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); 126 } else if (seekBar == mInWhiteSeekBar) { 127 mInWhite = (float)progress + 127.0f; 128 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); 129 } else if (seekBar == mOutWhiteSeekBar) { 130 mOutWhite = (float)progress + 127.0f; 131 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); 132 } else if (seekBar == mGammaSeekBar) { 133 mGamma = (float)progress/100.0f; 134 mGamma = Math.max(mGamma, 0.1f); 135 mGamma = 1.0f / mGamma; 136 mScriptVBlur.invoke_setGamma(mGamma); 137 } else if (seekBar == mSaturationSeekBar) { 138 mSaturation = (float)progress / 50.0f; 139 mScriptVBlur.invoke_setSaturation(mSaturation); 140 } 141 142 synchronized (mDisplayView) { 143 if (mIsProcessing) { 144 return; 145 } 146 mIsProcessing = true; 147 } 148 149 mScript.invoke_filter(); 150 } 151 } 152 153 public void onStartTrackingTouch(SeekBar seekBar) { 154 } 155 156 public void onStopTrackingTouch(SeekBar seekBar) { 157 } 158 159 @Override 160 protected void onCreate(Bundle savedInstanceState) { 161 super.onCreate(savedInstanceState); 162 setContentView(R.layout.main); 163 164 mBitmapIn = loadBitmap(R.drawable.city); 165 mBitmapOut = loadBitmap(R.drawable.city); 166 167 mSurfaceView = (SurfaceView) findViewById(R.id.surface); 168 mSurfaceView.getHolder().addCallback(this); 169 170 mDisplayView = (ImageView) findViewById(R.id.display); 171 mDisplayView.setImageBitmap(mBitmapOut); 172 173 mRadiusSeekBar = (SeekBar) findViewById(R.id.radius); 174 mRadiusSeekBar.setOnSeekBarChangeListener(this); 175 176 mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack); 177 mInBlackSeekBar.setOnSeekBarChangeListener(this); 178 mInBlackSeekBar.setMax(128); 179 mInBlackSeekBar.setProgress(0); 180 mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack); 181 mOutBlackSeekBar.setOnSeekBarChangeListener(this); 182 mOutBlackSeekBar.setMax(128); 183 mOutBlackSeekBar.setProgress(0); 184 185 mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite); 186 mInWhiteSeekBar.setOnSeekBarChangeListener(this); 187 mInWhiteSeekBar.setMax(128); 188 mInWhiteSeekBar.setProgress(128); 189 mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite); 190 mOutWhiteSeekBar.setOnSeekBarChangeListener(this); 191 mOutWhiteSeekBar.setMax(128); 192 mOutWhiteSeekBar.setProgress(128); 193 194 mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma); 195 mGammaSeekBar.setOnSeekBarChangeListener(this); 196 mGammaSeekBar.setMax(150); 197 mGammaSeekBar.setProgress(100); 198 199 mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation); 200 mSaturationSeekBar.setOnSeekBarChangeListener(this); 201 mSaturationSeekBar.setProgress(50); 202 203 mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); 204 mBenchmarkResult.setText("Result: not run"); 205 } 206 207 public void surfaceCreated(SurfaceHolder holder) { 208 createScript(); 209 mScript.invoke_filter(); 210 mOutPixelsAllocation.copyTo(mBitmapOut); 211 } 212 213 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 214 } 215 216 public void surfaceDestroyed(SurfaceHolder holder) { 217 } 218 219 private void createScript() { 220 mRS = RenderScript.create(this); 221 mRS.setMessageHandler(new FilterCallback()); 222 223 mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, 224 Allocation.MipmapControl.MIPMAP_NONE, 225 Allocation.USAGE_SCRIPT); 226 mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut, 227 Allocation.MipmapControl.MIPMAP_NONE, 228 Allocation.USAGE_SCRIPT); 229 230 Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS)); 231 tb.setX(mBitmapIn.getWidth()); 232 tb.setY(mBitmapIn.getHeight()); 233 mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create()); 234 mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create()); 235 236 mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur); 237 mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur); 238 239 mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold); 240 mScript.set_width(mBitmapIn.getWidth()); 241 mScript.set_height(mBitmapIn.getHeight()); 242 mScript.set_radius(mRadius); 243 244 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); 245 mScriptVBlur.invoke_setGamma(mGamma); 246 mScriptVBlur.invoke_setSaturation(mSaturation); 247 248 mScript.bind_InPixel(mInPixelsAllocation); 249 mScript.bind_OutPixel(mOutPixelsAllocation); 250 mScript.bind_ScratchPixel1(mScratchPixelsAllocation1); 251 mScript.bind_ScratchPixel2(mScratchPixelsAllocation2); 252 253 mScript.set_vBlurScript(mScriptVBlur); 254 mScript.set_hBlurScript(mScriptHBlur); 255 } 256 257 private Bitmap loadBitmap(int resource) { 258 final BitmapFactory.Options options = new BitmapFactory.Options(); 259 options.inPreferredConfig = Bitmap.Config.ARGB_8888; 260 return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options)); 261 } 262 263 private static Bitmap copyBitmap(Bitmap source) { 264 Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig()); 265 Canvas c = new Canvas(b); 266 c.drawBitmap(source, 0, 0, null); 267 source.recycle(); 268 return b; 269 } 270 271 // button hook 272 public void benchmark(View v) { 273 long t = getBenchmark(); 274 //long javaTime = javaFilter(); 275 //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms"); 276 mBenchmarkResult.setText("Result: " + t + " ms"); 277 } 278 279 // For benchmark test 280 public long getBenchmark() { 281 Log.v(TAG, "Benchmarking"); 282 int oldRadius = mRadius; 283 mRadius = MAX_RADIUS; 284 mScript.set_radius(mRadius); 285 286 long t = java.lang.System.currentTimeMillis(); 287 288 mScript.invoke_filter(); 289 mOutPixelsAllocation.copyTo(mBitmapOut); 290 291 t = java.lang.System.currentTimeMillis() - t; 292 Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t); 293 mRadius = oldRadius; 294 mScript.set_radius(mRadius); 295 296 mScript.invoke_filter(); 297 mOutPixelsAllocation.copyTo(mBitmapOut); 298 return t; 299 } 300 } 301