USM Image Processing On Android

The Unsharp Mask filter sharpens edges of the elements without increasing noise or blemish. You can refer to GIMP doc to know how does an unsharp mask works. As my understanding, for each pixel = original + (original – blur)

In this example we will use the blurred image to obtain the USM image. In order to make it obvious we will apply the effect three times.

Algorithm:

1.) Create a new project by File-> New -> Android Project name it USMOnImageProcessing.

2.) Write following into main.xml:

<?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="Hello" />
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<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:scaleType="center"
android:src="@drawable/thumb"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Result" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageAfter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"/>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
</LinearLayout>
</ScrollView>
</HorizontalScrollView>
</LinearLayout>

3.) Run for output.

Steps:

1.) Create a project named USMOnImageProcessing and set the information as stated in the image.

Build Target: Android 4.4
Application Name: USMOnImageProcessing
Package Name: com.example.USMOnImageProcessing
Activity Name: USMOnImageProcessingActivity

usm1

2.) Open USMOnImageProcessingActivity.java file and write following code there:

package com.example.usmonimageprocessing;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
public class USMOnImageProcessingActivity extends Activity {
final static int KERNAL_WIDTH = 3;
final static int KERNAL_HEIGHT = 3;
int[][] kernal_blur = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
final static int DIV_BY_9 = 9;
ImageView imageSource, imageAfter;
Bitmap bitmap_Source;
ProgressBar progressBar;
private Handler handler;
Bitmap afterProcess;
/** 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);
progressBar = (ProgressBar)findViewById(R.id.progressBar);
bitmap_Source = BitmapFactory.decodeResource(getResources(), R.drawable.thumb);
handler = new Handler();
StratBackgroundProcess();
}
private void StratBackgroundProcess(){
Runnable runnable = new Runnable(){
@Override
public void run() {
afterProcess = processingBitmap(bitmap_Source, kernal_blur);
afterProcess = processingBitmap(afterProcess, kernal_blur);
afterProcess = processingBitmap(afterProcess, kernal_blur);
handler.post(new Runnable(){
@Override
public void run() {
progressBar.setVisibility(View.GONE);
imageAfter.setImageBitmap(afterProcess);
}
});
}
};
new Thread(runnable).start();
}
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;
int bmWidth_OFFSET_1 = 1;
int bmHeight_OFFSET_1 = 1;
for(int i = bmWidth_OFFSET_1; i <= bmWidth_MINUS_2; i++){
for(int j = bmHeight_OFFSET_1; j <= bmHeight_MINUS_2; j++){
//get the surround 7*7 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-bmWidth_OFFSET_1+k, j-bmHeight_OFFSET_1+l);
}
}
//subSum = subSrc[][] * knl[][]
long subSumA = 0;
long subSumR = 0;
long subSumG = 0;
long subSumB = 0;
for(int k = 0; k < KERNAL_WIDTH; k++){
for(int l = 0; l < KERNAL_HEIGHT; l++){
subSumA += (long)(Color.alpha(subSrc[k][l])) * (long)(knl[k][l]);
subSumR += (long)(Color.red(subSrc[k][l])) * (long)(knl[k][l]);
subSumG += (long)(Color.green(subSrc[k][l])) * (long)(knl[k][l]);
subSumB += (long)(Color.blue(subSrc[k][l])) * (long)(knl[k][l]);
}
}
subSumA = subSumA/DIV_BY_9;
subSumR = subSumR/DIV_BY_9;
subSumG = subSumG/DIV_BY_9;
subSumB = subSumB/DIV_BY_9;
int orgColor = src.getPixel(i, j);
int orgA = Color.alpha(orgColor);
int orgR = Color.red(orgColor);
int orgG = Color.green(orgColor);
int orgB = Color.blue(orgColor);
subSumA = orgA + (orgA - subSumA);
subSumR = orgR + (orgR - subSumR);
subSumG = orgG + (orgG - subSumG);
subSumB = orgB + (orgB - subSumB);
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(
(int)subSumA,
(int)subSumR,
(int)subSumG,
(int)subSumB));
}
}
return dest;
}
}

3.) Compile and build the project.

Output

usm2

usm3