/* * 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 java.lang.Math; public class ImageProcessingActivity extends Activity implements SurfaceHolder.Callback { private Bitmap mBitmap; private Params mParams; private Script.Invokable mInvokable; private int[] mInData; private int[] mOutData; @SuppressWarnings({"FieldCanBeLocal"}) private RenderScript mRS; @SuppressWarnings({"FieldCanBeLocal"}) private Type mParamsType; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mParamsAllocation; @SuppressWarnings({"FieldCanBeLocal"}) private Type mPixelType; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mInPixelsAllocation; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mOutPixelsAllocation; private SurfaceView mSurfaceView; private ImageView mDisplayView; static class Params { public int inWidth; public int outWidth; public int inHeight; public int outHeight; public float threshold; } static class Pixel { public byte a; public byte r; public byte g; public byte b; } class FilterCallback extends RenderScript.RSMessage { private Runnable mAction = new Runnable() { public void run() { mOutPixelsAllocation.readData(mOutData); mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, mParams.outWidth, mParams.outHeight); mDisplayView.invalidate(); } }; @Override public void run() { mSurfaceView.removeCallbacks(mAction); mSurfaceView.post(mAction); } } private void javaFilter() { long t = java.lang.System.currentTimeMillis(); int count = mParams.inWidth * mParams.inHeight; float threshold = mParams.threshold * 255.f; for (int i = 0; i < count; i++) { final float r = (float)((mInData[i] >> 0) & 0xff); final float g = (float)((mInData[i] >> 8) & 0xff); final float b = (float)((mInData[i] >> 16) & 0xff); final float luminance = 0.2125f * r + 0.7154f * g + 0.0721f * b; if (luminance > threshold) { mOutData[i] = mInData[i]; } else { mOutData[i] = mInData[i] & 0xff000000; } } t = java.lang.System.currentTimeMillis() - t; android.util.Log.v("Img", "frame time ms " + t); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mBitmap = loadBitmap(R.drawable.data); mSurfaceView = (SurfaceView) findViewById(R.id.surface); mSurfaceView.getHolder().addCallback(this); mDisplayView = (ImageView) findViewById(R.id.display); mDisplayView.setImageBitmap(mBitmap); ((SeekBar) findViewById(R.id.threshold)).setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { mParams.threshold = progress / 100.0f; mParamsAllocation.data(mParams); if (true) { mInvokable.execute(); } else { javaFilter(); mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, mParams.outWidth, mParams.outHeight); mDisplayView.invalidate(); } } } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { } }); } public void surfaceCreated(SurfaceHolder holder) { mParams = createParams(); mInvokable = createScript(); mInvokable.execute(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceDestroyed(SurfaceHolder holder) { } private Script.Invokable createScript() { mRS = RenderScript.create(); mRS.mMessageCallback = new FilterCallback(); mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters"); mParamsAllocation = Allocation.createTyped(mRS, mParamsType); mParamsAllocation.data(mParams); final int pixelCount = mParams.inWidth * mParams.inHeight; mPixelType = Type.createFromClass(mRS, Pixel.class, 1, "Pixel"); mInPixelsAllocation = Allocation.createSized(mRS, Element.createUser(mRS, Element.DataType.SIGNED_32), pixelCount); mOutPixelsAllocation = Allocation.createSized(mRS, Element.createUser(mRS, Element.DataType.SIGNED_32), pixelCount); mInData = new int[pixelCount]; mBitmap.getPixels(mInData, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight); mInPixelsAllocation.data(mInData); mOutData = new int[pixelCount]; mOutPixelsAllocation.data(mOutData); ScriptC.Builder sb = new ScriptC.Builder(mRS); sb.setType(mParamsType, "Params", 0); sb.setType(mPixelType, "InPixel", 1); sb.setType(mPixelType, "OutPixel", 2); sb.setType(true, 2); Script.Invokable invokable = sb.addInvokable("main"); sb.setScript(getResources(), R.raw.threshold); //sb.setRoot(true); ScriptC script = sb.create(); script.bindAllocation(mParamsAllocation, 0); script.bindAllocation(mInPixelsAllocation, 1); script.bindAllocation(mOutPixelsAllocation, 2); return invokable; } private Params createParams() { final Params params = new Params(); params.inWidth = params.outWidth = mBitmap.getWidth(); params.inHeight = params.outHeight = mBitmap.getHeight(); params.threshold = 0.5f; return params; } 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; } }