May 31, 2012

Image Processing with open JPG file dialog

In the former articles in my "Image processing" series, the source image is preset. With the example of "JPG File Chooser", a dialog to load jpg file is added. User can select image to be processed, by touching on MENU and Load jpg.

User can select jpg to process


Please notice that it is a heavy memory needed processing, may be you will get OutOfMemoryError!

Modify from the former article "Unsharp Mask (USM) on Android Image Processing".

Create /res/layout/load_dialog.xml to define the layout of the Load JPG dialog.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/customdialog"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="20dp"
    android:minWidth="300dp">
    <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"/>
        <Button
            android:id="@+id/up"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Parent folder"/>
    </LinearLayout>

 <TextView
     android:id="@+id/folder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ListView
        android:id="@+id/dialoglist"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>


Main code, AndroidImageProcessingActivity.java.
package com.AndroidImageProcessing;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.Dialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class AndroidImageProcessingActivity extends Activity {
 
 //for Load JPG dialog
 Button buttonUp;
 static final int LOAD_DIALOG_ID = 0;
 TextView textFolder;
 ListView dialog_ListView;
 private List<String> fileList = new ArrayList<String>();
 
 File root;
 File curFolder;
 
 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);
        progressBar.setVisibility(View.GONE);
        
        bitmap_Source = BitmapFactory.decodeResource(getResources(), R.drawable.testpicture);

        handler = new Handler();
        //performImageProcessing(bitmap_Source);
        
        root = new File(Environment
          .getExternalStorageDirectory()
          .getAbsolutePath());
        
        curFolder = root;
    }
    
    private void performImageProcessing(Bitmap bmSrc){
     imageSource.setImageBitmap(bmSrc);
     progressBar.setVisibility(View.VISIBLE);
  imageAfter.setVisibility(View.GONE);
     StratBackgroundProcess(bmSrc);
    }
    
    private void StratBackgroundProcess(final Bitmap bm_src){
     
     Runnable runnable = new Runnable(){

   @Override
   public void run() {
    afterProcess = processingBitmap(bm_src, kernal_blur);
    handler.post(new Runnable(){

     @Override
     public void run() {
      progressBar.setVisibility(View.GONE);
      imageAfter.setVisibility(View.VISIBLE);
      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;
    }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  menu.add(0, 0, 0, "Load jpg");
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  switch(item.getItemId()){
  case (0):
   showDialog(LOAD_DIALOG_ID);
   break;
  }
  return true;
 }

 @Override
 protected Dialog onCreateDialog(int id) {

  Dialog dialog = null;
  
  switch(id) {
     case LOAD_DIALOG_ID:
      dialog = new Dialog(AndroidImageProcessingActivity.this);
      dialog.setContentView(R.layout.load_dialog);
      dialog.setTitle("Load JPG");
      
      dialog.setCancelable(true);
      dialog.setCanceledOnTouchOutside(true);
      
      textFolder = (TextView)dialog.findViewById(R.id.folder);

      buttonUp = (Button)dialog.findViewById(R.id.up);
      buttonUp.setOnClickListener(new OnClickListener(){

    @Override
    public void onClick(View v) {
     // TODO Auto-generated method stub
     ListDir(curFolder.getParentFile());
    }});

      //Prepare ListView in dialog
      dialog_ListView = (ListView)dialog.findViewById(R.id.dialoglist);

      dialog_ListView.setOnItemClickListener(new OnItemClickListener(){

    @Override
    public void onItemClick(AdapterView<?> parent, View view,
      int position, long id) {
     
     File selected = new File(fileList.get(position));
     if(selected.isDirectory()){
      ListDir(selected); 
     }else {
      Toast.makeText(AndroidImageProcessingActivity.this,
        selected.toString() + " selected",
        Toast.LENGTH_LONG).show();
      dismissDialog(LOAD_DIALOG_ID);
      
      Bitmap bm = BitmapFactory.decodeFile(selected.getAbsolutePath());
      imageSource.setImageBitmap(bm);
            performImageProcessing(bm);
        }
     
    }});
      
         break;
     }

  return dialog;
 }

 @Override
 protected void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
  // TODO Auto-generated method stub
  super.onPrepareDialog(id, dialog, bundle);

  switch(id) {
     case LOAD_DIALOG_ID:
      ListDir(curFolder);
         break;
     }
  
 }
 
 void ListDir(File f){

  if(f.equals(root)){
   buttonUp.setEnabled(false);
  }else{
   buttonUp.setEnabled(true);
  }
  
  curFolder = f;
  textFolder.setText(f.getPath());
  
  File[] files = f.listFiles();
  fileList.clear();
  for (File file : files){
   
   if(file.isDirectory()){
    fileList.add(file.getPath());
   }else{
    Uri selectedUri = Uri.fromFile(file);
    String fileExtension
     = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString());
    if(fileExtension.equalsIgnoreCase("jpg")){
     fileList.add(file.getPath());
    }
   }
   
  }
       
  ArrayAdapter<String> directoryList
   = new ArrayAdapter<String>(this,
     android.R.layout.simple_list_item_1, fileList);
  dialog_ListView.setAdapter(directoryList);
 }

}


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="@string/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"/>
       <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>


No comments:

Post a Comment

Infolinks In Text Ads