May 15, 2012

Apply Blur effect on Android, using Convolution Matrix


Last article describe the basic logic of Convolution Matrix, it's used to apply Blur effect on Bitmap.

Apply Blur effect on Android, using Convolution Matrix


- The Kernal used for blur is:
{1, 1, 1
  1, 1, 1
  1, 1, 1}

- There are 9 '1' in the Kernal, so we have to divid the sum of each pixel by 9, to make it in the save level.

- Each color is limited within the range of 0~255.

- To make the blur effect more obviously, the processingBitmap of blur is called 5 times.

package com.AndroidImageProcessing;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.ImageView;

public class AndroidImageProcessingActivity extends Activity {
 
 final static int KERNAL_WIDTH = 3;
 final static int KERNAL_HEIGHT = 3;
 
 int[][] kernalBlur ={
   {1, 1, 1},
   {1, 1, 1},
   {1, 1, 1}
 };
 
 int DIV_BY_9 = 9;
 
 ImageView imageSource, imageAfter;
 Bitmap bitmap_Source;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        imageSource = (ImageView)findViewById(R.id.imageSource);
        imageAfter = (ImageView)findViewById(R.id.imageAfter);
        
        bitmap_Source = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        
        Bitmap afterBlur = processingBitmap(bitmap_Source, kernalBlur);
        afterBlur = processingBitmap(afterBlur, kernalBlur);
        afterBlur = processingBitmap(afterBlur, kernalBlur);
        afterBlur = processingBitmap(afterBlur, kernalBlur);
        afterBlur = processingBitmap(afterBlur, kernalBlur);
        imageAfter.setImageBitmap(afterBlur);
    }
    
    private Bitmap processingBitmap(Bitmap src, int[][] knl){
     Bitmap dest = Bitmap.createBitmap(
       src.getWidth(), src.getHeight(), src.getConfig());
     
     int bmWidth = src.getWidth();
     int bmHeight = src.getHeight();
     int bmWidth_MINUS_2 = bmWidth - 2;
     int bmHeight_MINUS_2 = bmHeight - 2;
     
     for(int i = 1; i <= bmWidth_MINUS_2; i++){
      for(int j = 1; j <= bmHeight_MINUS_2; j++){
       
       //get the surround 3*3 pixel of current src[i][j] into a matrix subSrc[][]
       int[][] subSrc = new int[KERNAL_WIDTH][KERNAL_HEIGHT];
       for(int k = 0; k < KERNAL_WIDTH; k++){
        for(int l = 0; l < KERNAL_HEIGHT; l++){
         subSrc[k][l] = src.getPixel(i-1+k, j-1+l);
        }
       }
       
       //subSum = subSrc[][] * knl[][]
       int subSumA = 0;
       int subSumR = 0;
       int subSumG = 0;
       int subSumB = 0;

       for(int k = 0; k < KERNAL_WIDTH; k++){
        for(int l = 0; l < KERNAL_HEIGHT; l++){
         subSumA += Color.alpha(subSrc[k][l]) * knl[k][l];
         subSumR += Color.red(subSrc[k][l]) * knl[k][l];
         subSumG += Color.green(subSrc[k][l]) * knl[k][l];
         subSumB += Color.blue(subSrc[k][l]) * knl[k][l];
        }
       }
       
       subSumA = subSumA/DIV_BY_9;
       subSumR = subSumR/DIV_BY_9;
       subSumG = subSumG/DIV_BY_9;
       subSumB = subSumB/DIV_BY_9;
       
       if(subSumA<0){
        subSumA = 0;
       }else if(subSumA>255){
        subSumA = 255;
       }
       
       if(subSumR<0){
        subSumR = 0;
       }else if(subSumR>255){
        subSumR = 255;
       }
       
       if(subSumG<0){
        subSumG = 0;
       }else if(subSumG>255){
        subSumG = 255;
       }
       
       if(subSumB<0){
        subSumB = 0;
       }else if(subSumB>255){
        subSumB = 255;
       }

       dest.setPixel(i, j, Color.argb(
         subSumA, 
         subSumR, 
         subSumG, 
         subSumB));
      } 
     }
     
     return dest;
    }

}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <ScrollView 
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <LinearLayout 
            android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:orientation="vertical" >
         <TextView
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:text="Original" />
      <ImageView
          android:id="@+id/imageSource" 
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" 
          android:src="@drawable/ic_launcher"/>
      <TextView
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:text="Result" />
      <ImageView
          android:id="@+id/imageAfter" 
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
      
     </LinearLayout>
    </ScrollView>

</LinearLayout>


Related:
- Sharpen image, using Convolution Matrix


3 comments:

  1. thank u it was very useful one to me

    ReplyDelete
  2. Hi
    can u please help me how to remove selected color from image , i am trying, but i am unable to remove touched area color

    ReplyDelete
  3. Hi,

    im reading you blog for ca. half a year, and i just want to say "thank you"!

    Very usefull stuff and very high rate of posts. Keep it up!

    ReplyDelete

Infolinks In Text Ads