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