blob: e77646397f9edb3b0a42c7a6407809632bb35f7c [file] [log] [blame]
Romain Guyd7fa1222009-10-09 16:05:25 -07001/*
2 * Copyright (C) 2009 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.renderscript.ScriptC;
25import android.renderscript.RenderScript;
26import android.renderscript.Type;
27import android.renderscript.Allocation;
28import android.renderscript.Element;
29import android.renderscript.Script;
30import android.view.SurfaceView;
31import android.view.SurfaceHolder;
32import android.widget.ImageView;
33import android.widget.SeekBar;
Alex Sakhartchouk814326b2010-05-19 16:28:27 -070034import android.widget.TextView;
35import android.view.View;
Jason Sams586f3b52010-02-10 18:07:37 -080036import java.lang.Math;
Romain Guyd7fa1222009-10-09 16:05:25 -070037
Alex Sakhartchouk814326b2010-05-19 16:28:27 -070038public class ImageProcessingActivity extends Activity
39 implements SurfaceHolder.Callback,
40 SeekBar.OnSeekBarChangeListener {
Jason Sams4d339932010-05-11 14:03:58 -070041 private Bitmap mBitmapIn;
42 private Bitmap mBitmapOut;
Stephen Hines93a958f2010-09-16 17:18:55 -070043 private ScriptC_threshold mScript;
44 private ScriptC_vertical_blur mScriptVBlur;
45 private ScriptC_horizontal_blur mScriptHBlur;
Alex Sakhartchouk814326b2010-05-19 16:28:27 -070046 private int mRadius = 0;
47 private SeekBar mRadiusSeekBar;
48
49 private float mInBlack = 0.0f;
50 private SeekBar mInBlackSeekBar;
51 private float mOutBlack = 0.0f;
52 private SeekBar mOutBlackSeekBar;
53 private float mInWhite = 255.0f;
54 private SeekBar mInWhiteSeekBar;
55 private float mOutWhite = 255.0f;
56 private SeekBar mOutWhiteSeekBar;
57 private float mGamma = 1.0f;
58 private SeekBar mGammaSeekBar;
59
60 private float mSaturation = 1.0f;
61 private SeekBar mSaturationSeekBar;
62
63 private TextView mBenchmarkResult;
Romain Guyd7fa1222009-10-09 16:05:25 -070064
65 @SuppressWarnings({"FieldCanBeLocal"})
66 private RenderScript mRS;
67 @SuppressWarnings({"FieldCanBeLocal"})
Romain Guyd7fa1222009-10-09 16:05:25 -070068 private Type mPixelType;
69 @SuppressWarnings({"FieldCanBeLocal"})
70 private Allocation mInPixelsAllocation;
71 @SuppressWarnings({"FieldCanBeLocal"})
72 private Allocation mOutPixelsAllocation;
Alex Sakhartchouk814326b2010-05-19 16:28:27 -070073 @SuppressWarnings({"FieldCanBeLocal"})
Jason Sams43c31422010-08-16 12:29:23 -070074 private Allocation mScratchPixelsAllocation1;
75 private Allocation mScratchPixelsAllocation2;
Romain Guyd7fa1222009-10-09 16:05:25 -070076
77 private SurfaceView mSurfaceView;
78 private ImageView mDisplayView;
79
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -070080 private boolean mIsProcessing;
81
Jason Samsbf6ef8d2010-12-06 15:59:59 -080082 class FilterCallback extends RenderScript.RSMessageHandler {
Romain Guyd7fa1222009-10-09 16:05:25 -070083 private Runnable mAction = new Runnable() {
84 public void run() {
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -070085
86 synchronized (mDisplayView) {
87 mIsProcessing = false;
88 }
89
90 // This is a hack to work around an invalidation bug
Alex Sakhartchouk9dc8b362011-04-26 17:19:41 -070091 mBitmapOut.setPixel(0, 0, 0);
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -070092 mOutPixelsAllocation.copyTo(mBitmapOut);
Romain Guyd7fa1222009-10-09 16:05:25 -070093 mDisplayView.invalidate();
94 }
Jason Sams718cd1f2009-12-23 14:35:29 -080095 };
Romain Guyd7fa1222009-10-09 16:05:25 -070096
97 @Override
98 public void run() {
99 mSurfaceView.removeCallbacks(mAction);
100 mSurfaceView.post(mAction);
101 }
102 }
103
Jason Sams4d339932010-05-11 14:03:58 -0700104 int in[];
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700105 int interm[];
Jason Sams4d339932010-05-11 14:03:58 -0700106 int out[];
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700107 int MAX_RADIUS = 25;
108 // Store our coefficients here
109 float gaussian[];
110
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700111 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
112 if (fromUser) {
113
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800114 if (seekBar == mRadiusSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700115 float fRadius = progress / 100.0f;
116 fRadius *= (float)(MAX_RADIUS);
117 mRadius = (int)fRadius;
118
119 mScript.set_radius(mRadius);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800120 } else if (seekBar == mInBlackSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700121 mInBlack = (float)progress;
Jason Sams43c31422010-08-16 12:29:23 -0700122 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800123 } else if (seekBar == mOutBlackSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700124 mOutBlack = (float)progress;
Jason Sams43c31422010-08-16 12:29:23 -0700125 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800126 } else if (seekBar == mInWhiteSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700127 mInWhite = (float)progress + 127.0f;
Jason Sams43c31422010-08-16 12:29:23 -0700128 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800129 } else if (seekBar == mOutWhiteSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700130 mOutWhite = (float)progress + 127.0f;
Jason Sams43c31422010-08-16 12:29:23 -0700131 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800132 } else if (seekBar == mGammaSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700133 mGamma = (float)progress/100.0f;
134 mGamma = Math.max(mGamma, 0.1f);
135 mGamma = 1.0f / mGamma;
Jason Sams43c31422010-08-16 12:29:23 -0700136 mScriptVBlur.invoke_setGamma(mGamma);
Alex Sakhartchouked9f2102010-11-09 17:00:54 -0800137 } else if (seekBar == mSaturationSeekBar) {
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700138 mSaturation = (float)progress / 50.0f;
Jason Sams43c31422010-08-16 12:29:23 -0700139 mScriptVBlur.invoke_setSaturation(mSaturation);
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700140 }
141
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -0700142 synchronized (mDisplayView) {
143 if (mIsProcessing) {
144 return;
145 }
146 mIsProcessing = true;
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700147 }
148
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -0700149 mScript.invoke_filter();
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700150 }
151 }
152
153 public void onStartTrackingTouch(SeekBar seekBar) {
154 }
155
156 public void onStopTrackingTouch(SeekBar seekBar) {
Jason Sams586f3b52010-02-10 18:07:37 -0800157 }
158
Romain Guyd7fa1222009-10-09 16:05:25 -0700159 @Override
160 protected void onCreate(Bundle savedInstanceState) {
161 super.onCreate(savedInstanceState);
162 setContentView(R.layout.main);
163
Alex Sakhartchoukabf2b932011-04-22 12:42:47 -0700164 mBitmapIn = loadBitmap(R.drawable.city);
165 mBitmapOut = loadBitmap(R.drawable.city);
Romain Guyd7fa1222009-10-09 16:05:25 -0700166
167 mSurfaceView = (SurfaceView) findViewById(R.id.surface);
168 mSurfaceView.getHolder().addCallback(this);
169
170 mDisplayView = (ImageView) findViewById(R.id.display);
Jason Sams4d339932010-05-11 14:03:58 -0700171 mDisplayView.setImageBitmap(mBitmapOut);
Romain Guyd7fa1222009-10-09 16:05:25 -0700172
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700173 mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
174 mRadiusSeekBar.setOnSeekBarChangeListener(this);
Jason Sams586f3b52010-02-10 18:07:37 -0800175
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700176 mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
177 mInBlackSeekBar.setOnSeekBarChangeListener(this);
178 mInBlackSeekBar.setMax(128);
179 mInBlackSeekBar.setProgress(0);
180 mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
181 mOutBlackSeekBar.setOnSeekBarChangeListener(this);
182 mOutBlackSeekBar.setMax(128);
183 mOutBlackSeekBar.setProgress(0);
Romain Guyd7fa1222009-10-09 16:05:25 -0700184
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700185 mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
186 mInWhiteSeekBar.setOnSeekBarChangeListener(this);
187 mInWhiteSeekBar.setMax(128);
188 mInWhiteSeekBar.setProgress(128);
189 mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
190 mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
191 mOutWhiteSeekBar.setMax(128);
192 mOutWhiteSeekBar.setProgress(128);
Romain Guyd7fa1222009-10-09 16:05:25 -0700193
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700194 mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
195 mGammaSeekBar.setOnSeekBarChangeListener(this);
196 mGammaSeekBar.setMax(150);
197 mGammaSeekBar.setProgress(100);
198
199 mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
200 mSaturationSeekBar.setOnSeekBarChangeListener(this);
201 mSaturationSeekBar.setProgress(50);
202
203 mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
Alex Sakhartchoukdb217e02011-02-17 14:43:27 -0800204 mBenchmarkResult.setText("Result: not run");
Romain Guyd7fa1222009-10-09 16:05:25 -0700205 }
206
207 public void surfaceCreated(SurfaceHolder holder) {
Jason Sams4d339932010-05-11 14:03:58 -0700208 createScript();
Jason Samsf110d4b2010-06-21 17:42:41 -0700209 mScript.invoke_filter();
Jason Sams4ef66502010-12-10 16:03:15 -0800210 mOutPixelsAllocation.copyTo(mBitmapOut);
Romain Guyd7fa1222009-10-09 16:05:25 -0700211 }
212
213 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
214 }
215
216 public void surfaceDestroyed(SurfaceHolder holder) {
217 }
Jason Sams718cd1f2009-12-23 14:35:29 -0800218
Jason Sams4d339932010-05-11 14:03:58 -0700219 private void createScript() {
Shih-wei Liao6b32fab2010-12-10 01:03:59 -0800220 mRS = RenderScript.create(this);
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800221 mRS.setMessageHandler(new FilterCallback());
Romain Guyd7fa1222009-10-09 16:05:25 -0700222
Jason Sams4ef66502010-12-10 16:03:15 -0800223 mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
224 Allocation.MipmapControl.MIPMAP_NONE,
225 Allocation.USAGE_SCRIPT);
226 mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
227 Allocation.MipmapControl.MIPMAP_NONE,
228 Allocation.USAGE_SCRIPT);
Jason Sams43c31422010-08-16 12:29:23 -0700229
230 Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800231 tb.setX(mBitmapIn.getWidth());
232 tb.setY(mBitmapIn.getHeight());
Jason Sams43c31422010-08-16 12:29:23 -0700233 mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
234 mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
Romain Guyd7fa1222009-10-09 16:05:25 -0700235
Jason Sams3ba02b32010-11-03 23:01:38 -0700236 mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur);
237 mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur);
Jason Sams8f8a5722010-07-15 17:11:13 -0700238
Jason Sams3ba02b32010-11-03 23:01:38 -0700239 mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold);
Jason Sams4d339932010-05-11 14:03:58 -0700240 mScript.set_width(mBitmapIn.getWidth());
241 mScript.set_height(mBitmapIn.getHeight());
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700242 mScript.set_radius(mRadius);
243
Jason Sams43c31422010-08-16 12:29:23 -0700244 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
245 mScriptVBlur.invoke_setGamma(mGamma);
246 mScriptVBlur.invoke_setSaturation(mSaturation);
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700247
Jason Sams4d339932010-05-11 14:03:58 -0700248 mScript.bind_InPixel(mInPixelsAllocation);
249 mScript.bind_OutPixel(mOutPixelsAllocation);
Jason Sams43c31422010-08-16 12:29:23 -0700250 mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
251 mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
Jason Sams8f8a5722010-07-15 17:11:13 -0700252
253 mScript.set_vBlurScript(mScriptVBlur);
254 mScript.set_hBlurScript(mScriptHBlur);
Romain Guyd7fa1222009-10-09 16:05:25 -0700255 }
256
257 private Bitmap loadBitmap(int resource) {
258 final BitmapFactory.Options options = new BitmapFactory.Options();
259 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
260 return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
261 }
262
263 private static Bitmap copyBitmap(Bitmap source) {
264 Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
265 Canvas c = new Canvas(b);
266 c.drawBitmap(source, 0, 0, null);
267 source.recycle();
268 return b;
269 }
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700270
271 // button hook
272 public void benchmark(View v) {
273 android.util.Log.v("Img", "Benchmarking");
274 int oldRadius = mRadius;
275 mRadius = MAX_RADIUS;
276 mScript.set_radius(mRadius);
277
278 long t = java.lang.System.currentTimeMillis();
279
Jason Sams43c31422010-08-16 12:29:23 -0700280 mScript.invoke_filter();
Jason Sams4ef66502010-12-10 16:03:15 -0800281 mOutPixelsAllocation.copyTo(mBitmapOut);
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700282
283 t = java.lang.System.currentTimeMillis() - t;
284 android.util.Log.v("Img", "Renderscript frame time core ms " + t);
285
Jason Sams43c31422010-08-16 12:29:23 -0700286 //long javaTime = javaFilter();
287 //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms");
Alex Sakhartchoukdb217e02011-02-17 14:43:27 -0800288 mBenchmarkResult.setText("Result: " + t + " ms");
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700289
290 mRadius = oldRadius;
291 mScript.set_radius(mRadius);
292
Jason Samsf110d4b2010-06-21 17:42:41 -0700293 mScript.invoke_filter();
Jason Sams4ef66502010-12-10 16:03:15 -0800294 mOutPixelsAllocation.copyTo(mBitmapOut);
Alex Sakhartchouk814326b2010-05-19 16:28:27 -0700295 }
Romain Guyd7fa1222009-10-09 16:05:25 -0700296}