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