/* * 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 android.util.Log; import java.lang.Math; public class ImageProcessingActivity extends Activity implements SurfaceHolder.Callback, SeekBar.OnSeekBarChangeListener { private final String TAG = "Img"; 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; } 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) { long t = getBenchmark(); //long javaTime = javaFilter(); //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms"); mBenchmarkResult.setText("Result: " + t + " ms"); } // For benchmark test public long getBenchmark() { Log.v(TAG, "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; Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t); mRadius = oldRadius; mScript.set_radius(mRadius); mScript.invoke_filter(); mOutPixelsAllocation.copyTo(mBitmapOut); return t; } }