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