blob: e77646397f9edb3b0a42c7a6407809632bb35f7c [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.rs.image;
import android.app.Activity;
import android.os.Bundle;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.renderscript.ScriptC;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.Script;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.view.View;
import java.lang.Math;
public class ImageProcessingActivity extends Activity
implements SurfaceHolder.Callback,
SeekBar.OnSeekBarChangeListener {
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private ScriptC_threshold mScript;
private ScriptC_vertical_blur mScriptVBlur;
private ScriptC_horizontal_blur mScriptHBlur;
private int mRadius = 0;
private SeekBar mRadiusSeekBar;
private float mInBlack = 0.0f;
private SeekBar mInBlackSeekBar;
private float mOutBlack = 0.0f;
private SeekBar mOutBlackSeekBar;
private float mInWhite = 255.0f;
private SeekBar mInWhiteSeekBar;
private float mOutWhite = 255.0f;
private SeekBar mOutWhiteSeekBar;
private float mGamma = 1.0f;
private SeekBar mGammaSeekBar;
private float mSaturation = 1.0f;
private SeekBar mSaturationSeekBar;
private TextView mBenchmarkResult;
@SuppressWarnings({"FieldCanBeLocal"})
private RenderScript mRS;
@SuppressWarnings({"FieldCanBeLocal"})
private Type mPixelType;
@SuppressWarnings({"FieldCanBeLocal"})
private Allocation mInPixelsAllocation;
@SuppressWarnings({"FieldCanBeLocal"})
private Allocation mOutPixelsAllocation;
@SuppressWarnings({"FieldCanBeLocal"})
private Allocation mScratchPixelsAllocation1;
private Allocation mScratchPixelsAllocation2;
private SurfaceView mSurfaceView;
private ImageView mDisplayView;
private boolean mIsProcessing;
class FilterCallback extends RenderScript.RSMessageHandler {
private Runnable mAction = new Runnable() {
public void run() {
synchronized (mDisplayView) {
mIsProcessing = false;
}
// This is a hack to work around an invalidation bug
mBitmapOut.setPixel(0, 0, 0);
mOutPixelsAllocation.copyTo(mBitmapOut);
mDisplayView.invalidate();
}
};
@Override
public void run() {
mSurfaceView.removeCallbacks(mAction);
mSurfaceView.post(mAction);
}
}
int in[];
int interm[];
int out[];
int MAX_RADIUS = 25;
// Store our coefficients here
float gaussian[];
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
if (seekBar == mRadiusSeekBar) {
float fRadius = progress / 100.0f;
fRadius *= (float)(MAX_RADIUS);
mRadius = (int)fRadius;
mScript.set_radius(mRadius);
} else if (seekBar == mInBlackSeekBar) {
mInBlack = (float)progress;
mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
} else if (seekBar == mOutBlackSeekBar) {
mOutBlack = (float)progress;
mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
} else if (seekBar == mInWhiteSeekBar) {
mInWhite = (float)progress + 127.0f;
mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
} else if (seekBar == mOutWhiteSeekBar) {
mOutWhite = (float)progress + 127.0f;
mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
} else if (seekBar == mGammaSeekBar) {
mGamma = (float)progress/100.0f;
mGamma = Math.max(mGamma, 0.1f);
mGamma = 1.0f / mGamma;
mScriptVBlur.invoke_setGamma(mGamma);
} else if (seekBar == mSaturationSeekBar) {
mSaturation = (float)progress / 50.0f;
mScriptVBlur.invoke_setSaturation(mSaturation);
}
synchronized (mDisplayView) {
if (mIsProcessing) {
return;
}
mIsProcessing = true;
}
mScript.invoke_filter();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBitmapIn = loadBitmap(R.drawable.city);
mBitmapOut = loadBitmap(R.drawable.city);
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mSurfaceView.getHolder().addCallback(this);
mDisplayView = (ImageView) findViewById(R.id.display);
mDisplayView.setImageBitmap(mBitmapOut);
mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
mRadiusSeekBar.setOnSeekBarChangeListener(this);
mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
mInBlackSeekBar.setOnSeekBarChangeListener(this);
mInBlackSeekBar.setMax(128);
mInBlackSeekBar.setProgress(0);
mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
mOutBlackSeekBar.setOnSeekBarChangeListener(this);
mOutBlackSeekBar.setMax(128);
mOutBlackSeekBar.setProgress(0);
mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
mInWhiteSeekBar.setOnSeekBarChangeListener(this);
mInWhiteSeekBar.setMax(128);
mInWhiteSeekBar.setProgress(128);
mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
mOutWhiteSeekBar.setMax(128);
mOutWhiteSeekBar.setProgress(128);
mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
mGammaSeekBar.setOnSeekBarChangeListener(this);
mGammaSeekBar.setMax(150);
mGammaSeekBar.setProgress(100);
mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
mSaturationSeekBar.setOnSeekBarChangeListener(this);
mSaturationSeekBar.setProgress(50);
mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
mBenchmarkResult.setText("Result: not run");
}
public void surfaceCreated(SurfaceHolder holder) {
createScript();
mScript.invoke_filter();
mOutPixelsAllocation.copyTo(mBitmapOut);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void createScript() {
mRS = RenderScript.create(this);
mRS.setMessageHandler(new FilterCallback());
mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
tb.setX(mBitmapIn.getWidth());
tb.setY(mBitmapIn.getHeight());
mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur);
mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur);
mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold);
mScript.set_width(mBitmapIn.getWidth());
mScript.set_height(mBitmapIn.getHeight());
mScript.set_radius(mRadius);
mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
mScriptVBlur.invoke_setGamma(mGamma);
mScriptVBlur.invoke_setSaturation(mSaturation);
mScript.bind_InPixel(mInPixelsAllocation);
mScript.bind_OutPixel(mOutPixelsAllocation);
mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
mScript.set_vBlurScript(mScriptVBlur);
mScript.set_hBlurScript(mScriptHBlur);
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
}
private static Bitmap copyBitmap(Bitmap source) {
Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
Canvas c = new Canvas(b);
c.drawBitmap(source, 0, 0, null);
source.recycle();
return b;
}
// button hook
public void benchmark(View v) {
android.util.Log.v("Img", "Benchmarking");
int oldRadius = mRadius;
mRadius = MAX_RADIUS;
mScript.set_radius(mRadius);
long t = java.lang.System.currentTimeMillis();
mScript.invoke_filter();
mOutPixelsAllocation.copyTo(mBitmapOut);
t = java.lang.System.currentTimeMillis() - t;
android.util.Log.v("Img", "Renderscript frame time core ms " + t);
//long javaTime = javaFilter();
//mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms");
mBenchmarkResult.setText("Result: " + t + " ms");
mRadius = oldRadius;
mScript.set_radius(mRadius);
mScript.invoke_filter();
mOutPixelsAllocation.copyTo(mBitmapOut);
}
}