ImageProcessingActivity.java revision 89e20d27effd875431087a9188b20386b9c5aff0
1/* 2 * Copyright (C) 2012 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 17package com.android.rs.image; 18 19import android.app.Activity; 20import android.os.Bundle; 21import android.os.Handler; 22import android.os.Message; 23import android.graphics.BitmapFactory; 24import android.graphics.Bitmap; 25import android.graphics.Canvas; 26import android.view.SurfaceView; 27import android.widget.AdapterView; 28import android.widget.ArrayAdapter; 29import android.widget.ImageView; 30import android.widget.SeekBar; 31import android.widget.Spinner; 32import android.widget.TextView; 33import android.view.View; 34import android.util.Log; 35import android.renderscript.ScriptC; 36import android.renderscript.RenderScript; 37import android.renderscript.Type; 38import android.renderscript.Allocation; 39import android.renderscript.Element; 40import android.renderscript.Script; 41 42import android.os.Environment; 43import java.io.BufferedWriter; 44import java.io.File; 45import java.io.FileWriter; 46import java.io.IOException; 47 48public class ImageProcessingActivity extends Activity 49 implements SeekBar.OnSeekBarChangeListener { 50 private final String TAG = "Img"; 51 public final String RESULT_FILE = "image_processing_result.csv"; 52 53 RenderScript mRS; 54 Allocation mInPixelsAllocation; 55 Allocation mInPixelsAllocation2; 56 Allocation mOutPixelsAllocation; 57 58 /** 59 * Define enum type for test names 60 */ 61 public enum TestName { 62 // totally there are 38 test cases 63 LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"), 64 LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"), 65 LEVELS_VEC3_FULL ("Levels Vec3 Full"), 66 LEVELS_VEC4_FULL ("Levels Vec4 Full"), 67 BLUR_RADIUS_25 ("Blur radius 25"), 68 INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"), 69 GREYSCALE ("Greyscale"), 70 GRAIN ("Grain"), 71 FISHEYE_FULL ("Fisheye Full"), 72 FISHEYE_RELAXED ("Fisheye Relaxed"), 73 FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"), 74 FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"), 75 VIGNETTE_FULL ("Vignette Full"), 76 VIGNETTE_RELAXED ("Vignette Relaxed"), 77 VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"), 78 VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"), 79 GROUP_TEST_EMULATED ("Group Test (emulated)"), 80 GROUP_TEST_NATIVE ("Group Test (native)"), 81 CONVOLVE_3X3 ("Convolve 3x3"), 82 INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"), 83 COLOR_MATRIX ("ColorMatrix"), 84 INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"), 85 INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"), 86 COPY ("Copy"), 87 CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"), 88 CONVOLVE_5X5 ("Convolve 5x5"), 89 INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"), 90 MANDELBROT ("Mandelbrot"), 91 INTRINSICS_BLEND ("Intrinsics Blend"), 92 INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"), 93 VIBRANCE ("Vibrance"), 94 BW_FILTER ("BW Filter"), 95 SHADOWS ("Shadows"), 96 CONTRAST ("Contrast"), 97 EXPOSURE ("Exposure"), 98 WHITE_BALANCE ("White Balance"), 99 COLOR_CUBE ("Color Cube"), 100 COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)"), 101 USAGE_IO ("Usage io)"); 102 103 104 private final String name; 105 106 private TestName(String s) { 107 name = s; 108 } 109 110 // return quoted string as displayed test name 111 public String toString() { 112 return name; 113 } 114 } 115 116 Bitmap mBitmapIn; 117 Bitmap mBitmapIn2; 118 Bitmap mBitmapOut; 119 120 private Spinner mSpinner; 121 private SeekBar mBar1; 122 private SeekBar mBar2; 123 private SeekBar mBar3; 124 private SeekBar mBar4; 125 private SeekBar mBar5; 126 private TextView mText1; 127 private TextView mText2; 128 private TextView mText3; 129 private TextView mText4; 130 private TextView mText5; 131 132 private float mSaturation = 1.0f; 133 134 private TextView mBenchmarkResult; 135 private Spinner mTestSpinner; 136 137 private SurfaceView mSurfaceView; 138 private ImageView mDisplayView; 139 140 private boolean mDoingBenchmark; 141 142 private TestBase mTest; 143 private int mRunCount; 144 145 public void updateDisplay() { 146 mHandler.sendMessage(Message.obtain()); 147 } 148 149 private Handler mHandler = new Handler() { 150 // Allow the filter to complete without blocking the UI 151 // thread. When the message arrives that the op is complete 152 // we will either mark completion or start a new filter if 153 // more work is ready. Either way, display the result. 154 @Override 155 public void handleMessage(Message msg) { 156 boolean doTest = false; 157 synchronized(this) { 158 if (mRS == null) { 159 return; 160 } 161 mTest.updateBitmap(mBitmapOut); 162 mDisplayView.invalidate(); 163 if (mRunCount > 0) { 164 mRunCount--; 165 if (mRunCount > 0) { 166 doTest = true; 167 } 168 } 169 170 if (doTest) { 171 mTest.runTestSendMessage(); 172 } 173 } 174 } 175 176 }; 177 178 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 179 if (fromUser) { 180 181 if (seekBar == mBar1) { 182 mTest.onBar1Changed(progress); 183 } else if (seekBar == mBar2) { 184 mTest.onBar2Changed(progress); 185 } else if (seekBar == mBar3) { 186 mTest.onBar3Changed(progress); 187 } else if (seekBar == mBar4) { 188 mTest.onBar4Changed(progress); 189 } else if (seekBar == mBar5) { 190 mTest.onBar5Changed(progress); 191 } 192 193 boolean doTest = false; 194 synchronized(this) { 195 if (mRunCount == 0) { 196 doTest = true; 197 mRunCount = 1; 198 } else { 199 mRunCount = 2; 200 } 201 } 202 if (doTest) { 203 mTest.runTestSendMessage(); 204 } 205 } 206 } 207 208 public void onStartTrackingTouch(SeekBar seekBar) { 209 } 210 211 public void onStopTrackingTouch(SeekBar seekBar) { 212 } 213 214 void setupBars() { 215 mSpinner.setVisibility(View.VISIBLE); 216 mTest.onSpinner1Setup(mSpinner); 217 218 mBar1.setVisibility(View.VISIBLE); 219 mText1.setVisibility(View.VISIBLE); 220 mTest.onBar1Setup(mBar1, mText1); 221 222 mBar2.setVisibility(View.VISIBLE); 223 mText2.setVisibility(View.VISIBLE); 224 mTest.onBar2Setup(mBar2, mText2); 225 226 mBar3.setVisibility(View.VISIBLE); 227 mText3.setVisibility(View.VISIBLE); 228 mTest.onBar3Setup(mBar3, mText3); 229 230 mBar4.setVisibility(View.VISIBLE); 231 mText4.setVisibility(View.VISIBLE); 232 mTest.onBar4Setup(mBar4, mText4); 233 234 mBar5.setVisibility(View.VISIBLE); 235 mText5.setVisibility(View.VISIBLE); 236 mTest.onBar5Setup(mBar5, mText5); 237 } 238 239 240 void changeTest(TestName testName) { 241 if (mTest != null) { 242 mTest.destroy(); 243 } 244 switch(testName) { 245 case LEVELS_VEC3_RELAXED: 246 mTest = new LevelsV4(false, false); 247 break; 248 case LEVELS_VEC4_RELAXED: 249 mTest = new LevelsV4(false, true); 250 break; 251 case LEVELS_VEC3_FULL: 252 mTest = new LevelsV4(true, false); 253 break; 254 case LEVELS_VEC4_FULL: 255 mTest = new LevelsV4(true, true); 256 break; 257 case BLUR_RADIUS_25: 258 mTest = new Blur25(false); 259 break; 260 case INTRINSIC_BLUE_RADIUS_25: 261 mTest = new Blur25(true); 262 break; 263 case GREYSCALE: 264 mTest = new Greyscale(); 265 break; 266 case GRAIN: 267 mTest = new Grain(); 268 break; 269 case FISHEYE_FULL: 270 mTest = new Fisheye(false, false); 271 break; 272 case FISHEYE_RELAXED: 273 mTest = new Fisheye(false, true); 274 break; 275 case FISHEYE_APPROXIMATE_FULL: 276 mTest = new Fisheye(true, false); 277 break; 278 case FISHEYE_APPROXIMATE_RELAXED: 279 mTest = new Fisheye(true, true); 280 break; 281 case VIGNETTE_FULL: 282 mTest = new Vignette(false, false); 283 break; 284 case VIGNETTE_RELAXED: 285 mTest = new Vignette(false, true); 286 break; 287 case VIGNETTE_APPROXIMATE_FULL: 288 mTest = new Vignette(true, false); 289 break; 290 case VIGNETTE_APPROXIMATE_RELAXED: 291 mTest = new Vignette(true, true); 292 break; 293 case GROUP_TEST_EMULATED: 294 mTest = new GroupTest(false); 295 break; 296 case GROUP_TEST_NATIVE: 297 mTest = new GroupTest(true); 298 break; 299 case CONVOLVE_3X3: 300 mTest = new Convolve3x3(false); 301 break; 302 case INTRINSICS_CONVOLVE_3X3: 303 mTest = new Convolve3x3(true); 304 break; 305 case COLOR_MATRIX: 306 mTest = new ColorMatrix(false, false); 307 break; 308 case INTRINSICS_COLOR_MATRIX: 309 mTest = new ColorMatrix(true, false); 310 break; 311 case INTRINSICS_COLOR_MATRIX_GREY: 312 mTest = new ColorMatrix(true, true); 313 break; 314 case COPY: 315 mTest = new Copy(); 316 break; 317 case CROSS_PROCESS_USING_LUT: 318 mTest = new CrossProcess(); 319 break; 320 case CONVOLVE_5X5: 321 mTest = new Convolve5x5(false); 322 break; 323 case INTRINSICS_CONVOLVE_5X5: 324 mTest = new Convolve5x5(true); 325 break; 326 case MANDELBROT: 327 mTest = new Mandelbrot(); 328 break; 329 case INTRINSICS_BLEND: 330 mTest = new Blend(); 331 break; 332 case INTRINSICS_BLUR_25G: 333 mTest = new Blur25G(); 334 break; 335 case VIBRANCE: 336 mTest = new Vibrance(); 337 break; 338 case BW_FILTER: 339 mTest = new BWFilter(); 340 break; 341 case SHADOWS: 342 mTest = new Shadows(); 343 break; 344 case CONTRAST: 345 mTest = new Contrast(); 346 break; 347 case EXPOSURE: 348 mTest = new Exposure(); 349 break; 350 case WHITE_BALANCE: 351 mTest = new WhiteBalance(); 352 break; 353 case COLOR_CUBE: 354 mTest = new ColorCube(false); 355 break; 356 case COLOR_CUBE_3D_INTRINSIC: 357 mTest = new ColorCube(true); 358 break; 359 case USAGE_IO: 360 mTest = new UsageIO(); 361 break; 362 } 363 364 mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut); 365 setupBars(); 366 367 mTest.runTest(); 368 updateDisplay(); 369 mBenchmarkResult.setText("Result: not run"); 370 } 371 372 void setupTests() { 373 mTestSpinner.setAdapter(new ArrayAdapter<TestName>( 374 this, R.layout.spinner_layout, TestName.values())); 375 } 376 377 private AdapterView.OnItemSelectedListener mTestSpinnerListener = 378 new AdapterView.OnItemSelectedListener() { 379 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 380 changeTest(TestName.values()[pos]); 381 } 382 383 public void onNothingSelected(AdapterView parent) { 384 385 } 386 }; 387 388 void init() { 389 mBitmapIn = loadBitmap(R.drawable.img1600x1067); 390 mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b); 391 mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(), 392 mBitmapIn.getConfig()); 393 394 mSurfaceView = (SurfaceView) findViewById(R.id.surface); 395 396 mDisplayView = (ImageView) findViewById(R.id.display); 397 mDisplayView.setImageBitmap(mBitmapOut); 398 399 mSpinner = (Spinner) findViewById(R.id.spinner1); 400 401 mBar1 = (SeekBar) findViewById(R.id.slider1); 402 mBar2 = (SeekBar) findViewById(R.id.slider2); 403 mBar3 = (SeekBar) findViewById(R.id.slider3); 404 mBar4 = (SeekBar) findViewById(R.id.slider4); 405 mBar5 = (SeekBar) findViewById(R.id.slider5); 406 407 mBar1.setOnSeekBarChangeListener(this); 408 mBar2.setOnSeekBarChangeListener(this); 409 mBar3.setOnSeekBarChangeListener(this); 410 mBar4.setOnSeekBarChangeListener(this); 411 mBar5.setOnSeekBarChangeListener(this); 412 413 mText1 = (TextView) findViewById(R.id.slider1Text); 414 mText2 = (TextView) findViewById(R.id.slider2Text); 415 mText3 = (TextView) findViewById(R.id.slider3Text); 416 mText4 = (TextView) findViewById(R.id.slider4Text); 417 mText5 = (TextView) findViewById(R.id.slider5Text); 418 419 mTestSpinner = (Spinner) findViewById(R.id.filterselection); 420 mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener); 421 422 mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); 423 mBenchmarkResult.setText("Result: not run"); 424 425 426 mRS = RenderScript.create(this); 427 mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, 428 Allocation.MipmapControl.MIPMAP_NONE, 429 Allocation.USAGE_SHARED | 430 Allocation.USAGE_GRAPHICS_TEXTURE | 431 Allocation.USAGE_SCRIPT); 432 mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2, 433 Allocation.MipmapControl.MIPMAP_NONE, 434 Allocation.USAGE_SHARED | 435 Allocation.USAGE_GRAPHICS_TEXTURE | 436 Allocation.USAGE_SCRIPT); 437 mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut); 438 439 440 setupTests(); 441 changeTest(TestName.LEVELS_VEC3_RELAXED); 442 } 443 444 void cleanup() { 445 synchronized(this) { 446 RenderScript rs = mRS; 447 mRS = null; 448 while(mDoingBenchmark) { 449 try { 450 Thread.sleep(1, 0); 451 } catch(InterruptedException e) { 452 } 453 454 } 455 rs.destroy(); 456 } 457 458 mInPixelsAllocation = null; 459 mInPixelsAllocation2 = null; 460 mOutPixelsAllocation = null; 461 mBitmapIn = null; 462 mBitmapIn2 = null; 463 mBitmapOut = null; 464 } 465 466 @Override 467 protected void onCreate(Bundle savedInstanceState) { 468 super.onCreate(savedInstanceState); 469 setContentView(R.layout.main); 470 471 init(); 472 } 473 474 @Override 475 protected void onPause() { 476 super.onPause(); 477 478 cleanup(); 479 } 480 481 482 @Override 483 protected void onResume() { 484 super.onResume(); 485 486 init(); 487 } 488 489 private Bitmap loadBitmap(int resource) { 490 final BitmapFactory.Options options = new BitmapFactory.Options(); 491 options.inPreferredConfig = Bitmap.Config.ARGB_8888; 492 return BitmapFactory.decodeResource(getResources(), resource, options); 493 } 494 495 // button hook 496 public void benchmark(View v) { 497 float t = getBenchmark(); 498 //long javaTime = javaFilter(); 499 //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms"); 500 mBenchmarkResult.setText("Result: " + t + " ms"); 501 Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t); 502 } 503 504 public void benchmark_all(View v) { 505 // write result into a file 506 File externalStorage = Environment.getExternalStorageDirectory(); 507 if (!externalStorage.canWrite()) { 508 Log.v(TAG, "sdcard is not writable"); 509 return; 510 } 511 File resultFile = new File(externalStorage, RESULT_FILE); 512 resultFile.setWritable(true, false); 513 try { 514 BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile)); 515 Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath()); 516 for (TestName tn: TestName.values()) { 517 changeTest(tn); 518 float t = getBenchmark(); 519 String s = new String("" + tn.toString() + ", " + t); 520 rsWriter.write(s + "\n"); 521 Log.v(TAG, "Test " + s + "ms\n"); 522 } 523 rsWriter.close(); 524 } catch (IOException e) { 525 Log.v(TAG, "Unable to write result file " + e.getMessage()); 526 } 527 changeTest(TestName.LEVELS_VEC3_RELAXED); 528 } 529 530 531 532 // For benchmark test 533 public float getBenchmark() { 534 if (mRS == null) { 535 return 0; 536 } 537 mDoingBenchmark = true; 538 539 mTest.setupBenchmark(); 540 long result = 0; 541 542 //Log.v(TAG, "Warming"); 543 long t = java.lang.System.currentTimeMillis() + 250; 544 do { 545 mTest.runTest(); 546 mTest.finish(); 547 } while (t > java.lang.System.currentTimeMillis()); 548 549 //Log.v(TAG, "Benchmarking"); 550 int ct = 0; 551 t = java.lang.System.currentTimeMillis(); 552 do { 553 mTest.runTest(); 554 mTest.finish(); 555 ct++; 556 } while ((t+1000) > java.lang.System.currentTimeMillis()); 557 t = java.lang.System.currentTimeMillis() - t; 558 float ft = (float)t; 559 ft /= ct; 560 561 mTest.exitBenchmark(); 562 mDoingBenchmark = false; 563 return ft; 564 } 565} 566