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