Home | History | Annotate | Download | only in image
      1 /*
      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 
     17 package com.android.rs.image;
     18 
     19 import android.app.Activity;
     20 import android.os.Bundle;
     21 import android.graphics.BitmapFactory;
     22 import android.graphics.Bitmap;
     23 import android.graphics.Canvas;
     24 import android.renderscript.ScriptC;
     25 import android.renderscript.RenderScript;
     26 import android.renderscript.Type;
     27 import android.renderscript.Allocation;
     28 import android.renderscript.Element;
     29 import android.renderscript.Script;
     30 import android.view.SurfaceView;
     31 import android.view.SurfaceHolder;
     32 import android.widget.ImageView;
     33 import android.widget.SeekBar;
     34 import android.widget.TextView;
     35 import android.view.View;
     36 import android.util.Log;
     37 import java.lang.Math;
     38 
     39 public class ImageProcessingActivity extends Activity
     40                                        implements SurfaceHolder.Callback,
     41                                        SeekBar.OnSeekBarChangeListener {
     42     private final String TAG = "Img";
     43     private Bitmap mBitmapIn;
     44     private Bitmap mBitmapOut;
     45     private ScriptC_threshold mScript;
     46     private ScriptC_vertical_blur mScriptVBlur;
     47     private ScriptC_horizontal_blur mScriptHBlur;
     48     private int mRadius = 0;
     49     private SeekBar mRadiusSeekBar;
     50 
     51     private float mInBlack = 0.0f;
     52     private SeekBar mInBlackSeekBar;
     53     private float mOutBlack = 0.0f;
     54     private SeekBar mOutBlackSeekBar;
     55     private float mInWhite = 255.0f;
     56     private SeekBar mInWhiteSeekBar;
     57     private float mOutWhite = 255.0f;
     58     private SeekBar mOutWhiteSeekBar;
     59     private float mGamma = 1.0f;
     60     private SeekBar mGammaSeekBar;
     61 
     62     private float mSaturation = 1.0f;
     63     private SeekBar mSaturationSeekBar;
     64 
     65     private TextView mBenchmarkResult;
     66 
     67     @SuppressWarnings({"FieldCanBeLocal"})
     68     private RenderScript mRS;
     69     @SuppressWarnings({"FieldCanBeLocal"})
     70     private Type mPixelType;
     71     @SuppressWarnings({"FieldCanBeLocal"})
     72     private Allocation mInPixelsAllocation;
     73     @SuppressWarnings({"FieldCanBeLocal"})
     74     private Allocation mOutPixelsAllocation;
     75     @SuppressWarnings({"FieldCanBeLocal"})
     76     private Allocation mScratchPixelsAllocation1;
     77     private Allocation mScratchPixelsAllocation2;
     78 
     79     private SurfaceView mSurfaceView;
     80     private ImageView mDisplayView;
     81 
     82     private boolean mIsProcessing;
     83 
     84     class FilterCallback extends RenderScript.RSMessageHandler {
     85         private Runnable mAction = new Runnable() {
     86             public void run() {
     87 
     88                 synchronized (mDisplayView) {
     89                     mIsProcessing = false;
     90                 }
     91 
     92                 mOutPixelsAllocation.copyTo(mBitmapOut);
     93                 mDisplayView.invalidate();
     94             }
     95         };
     96 
     97         @Override
     98         public void run() {
     99             mSurfaceView.removeCallbacks(mAction);
    100             mSurfaceView.post(mAction);
    101         }
    102     }
    103 
    104     int in[];
    105     int interm[];
    106     int out[];
    107     int MAX_RADIUS = 25;
    108     // Store our coefficients here
    109     float gaussian[];
    110 
    111     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    112         if (fromUser) {
    113 
    114             if (seekBar == mRadiusSeekBar) {
    115                 float fRadius = progress / 100.0f;
    116                 fRadius *= (float)(MAX_RADIUS);
    117                 mRadius = (int)fRadius;
    118 
    119                 mScript.set_radius(mRadius);
    120             } else if (seekBar == mInBlackSeekBar) {
    121                 mInBlack = (float)progress;
    122                 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
    123             } else if (seekBar == mOutBlackSeekBar) {
    124                 mOutBlack = (float)progress;
    125                 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
    126             } else if (seekBar == mInWhiteSeekBar) {
    127                 mInWhite = (float)progress + 127.0f;
    128                 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
    129             } else if (seekBar == mOutWhiteSeekBar) {
    130                 mOutWhite = (float)progress + 127.0f;
    131                 mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
    132             } else if (seekBar == mGammaSeekBar) {
    133                 mGamma = (float)progress/100.0f;
    134                 mGamma = Math.max(mGamma, 0.1f);
    135                 mGamma = 1.0f / mGamma;
    136                 mScriptVBlur.invoke_setGamma(mGamma);
    137             } else if (seekBar == mSaturationSeekBar) {
    138                 mSaturation = (float)progress / 50.0f;
    139                 mScriptVBlur.invoke_setSaturation(mSaturation);
    140             }
    141 
    142             synchronized (mDisplayView) {
    143                 if (mIsProcessing) {
    144                     return;
    145                 }
    146                 mIsProcessing = true;
    147             }
    148 
    149             mScript.invoke_filter();
    150         }
    151     }
    152 
    153     public void onStartTrackingTouch(SeekBar seekBar) {
    154     }
    155 
    156     public void onStopTrackingTouch(SeekBar seekBar) {
    157     }
    158 
    159     @Override
    160     protected void onCreate(Bundle savedInstanceState) {
    161         super.onCreate(savedInstanceState);
    162         setContentView(R.layout.main);
    163 
    164         mBitmapIn = loadBitmap(R.drawable.city);
    165         mBitmapOut = loadBitmap(R.drawable.city);
    166 
    167         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
    168         mSurfaceView.getHolder().addCallback(this);
    169 
    170         mDisplayView = (ImageView) findViewById(R.id.display);
    171         mDisplayView.setImageBitmap(mBitmapOut);
    172 
    173         mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
    174         mRadiusSeekBar.setOnSeekBarChangeListener(this);
    175 
    176         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);
    184 
    185         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);
    193 
    194         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);
    204         mBenchmarkResult.setText("Result: not run");
    205     }
    206 
    207     public void surfaceCreated(SurfaceHolder holder) {
    208         createScript();
    209         mScript.invoke_filter();
    210         mOutPixelsAllocation.copyTo(mBitmapOut);
    211     }
    212 
    213     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    214     }
    215 
    216     public void surfaceDestroyed(SurfaceHolder holder) {
    217     }
    218 
    219     private void createScript() {
    220         mRS = RenderScript.create(this);
    221         mRS.setMessageHandler(new FilterCallback());
    222 
    223         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);
    229 
    230         Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
    231         tb.setX(mBitmapIn.getWidth());
    232         tb.setY(mBitmapIn.getHeight());
    233         mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
    234         mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
    235 
    236         mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur);
    237         mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur);
    238 
    239         mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold);
    240         mScript.set_width(mBitmapIn.getWidth());
    241         mScript.set_height(mBitmapIn.getHeight());
    242         mScript.set_radius(mRadius);
    243 
    244         mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
    245         mScriptVBlur.invoke_setGamma(mGamma);
    246         mScriptVBlur.invoke_setSaturation(mSaturation);
    247 
    248         mScript.bind_InPixel(mInPixelsAllocation);
    249         mScript.bind_OutPixel(mOutPixelsAllocation);
    250         mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
    251         mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
    252 
    253         mScript.set_vBlurScript(mScriptVBlur);
    254         mScript.set_hBlurScript(mScriptHBlur);
    255     }
    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     }
    270 
    271     // button hook
    272     public void benchmark(View v) {
    273         long t = getBenchmark();
    274         //long javaTime = javaFilter();
    275         //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
    276         mBenchmarkResult.setText("Result: " + t + " ms");
    277     }
    278 
    279     // For benchmark test
    280     public long getBenchmark() {
    281         Log.v(TAG, "Benchmarking");
    282         int oldRadius = mRadius;
    283         mRadius = MAX_RADIUS;
    284         mScript.set_radius(mRadius);
    285 
    286         mScript.invoke_filter();
    287         mRS.finish();
    288 
    289         long t = java.lang.System.currentTimeMillis();
    290 
    291         mScript.invoke_filter();
    292         mOutPixelsAllocation.copyTo(mBitmapOut);
    293 
    294         t = java.lang.System.currentTimeMillis() - t;
    295         Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
    296         mRadius = oldRadius;
    297         mScript.set_radius(mRadius);
    298 
    299         mScript.invoke_filter();
    300         mOutPixelsAllocation.copyTo(mBitmapOut);
    301         return t;
    302     }
    303 }
    304