Wednesday, August 14, 2013

Combine bitmap side-by-side

This exercise demonstrate how to combine two bitmap to one, using canvas. The source images are get from build-in Gallery app with intent ACTION_PICK. The width of the combined bitmap will be the sum of the width of the images. The height will be the that of the higher image.

This exercise have not take care the bitmap size, and any resizing. So don't test with big picture, otherwise OutOfMemoryError or "Bitmap too large to be uploaded into a texture" will happen.

Combine bitmap side-by-side


package com.example.androidimageprocessing;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 Button btnLoadImage1, btnLoadImage2;
 TextView textSource1, textSource2;
 Button btnProcessing;
 ImageView imageResult;
 
 final int RQS_IMAGE1 = 1;
 final int RQS_IMAGE2 = 2;
 
 Uri source1, source2;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnLoadImage1 = (Button)findViewById(R.id.loadimage1);
  btnLoadImage2 = (Button)findViewById(R.id.loadimage2);
  textSource1 = (TextView)findViewById(R.id.sourceuri1);
  textSource2 = (TextView)findViewById(R.id.sourceuri2);
  btnProcessing = (Button)findViewById(R.id.processing);
  imageResult = (ImageView)findViewById(R.id.result);
  
  btnLoadImage1.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }});
  
  btnLoadImage2.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE2);
   }});
  
  btnProcessing.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    
    if(source1 != null && source2 != null){
     Bitmap processedBitmap = ProcessingBitmap();
     if(processedBitmap != null){
      imageResult.setImageBitmap(processedBitmap);
      Toast.makeText(getApplicationContext(), 
        "Done", 
        Toast.LENGTH_LONG).show();
     }else{
      Toast.makeText(getApplicationContext(), 
        "Something wrong in processing!", 
        Toast.LENGTH_LONG).show();
     }
    }else{
     Toast.makeText(getApplicationContext(), 
       "Select both image!", 
       Toast.LENGTH_LONG).show();
    }
    
   }});
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if(resultCode == RESULT_OK){
   switch (requestCode){
   case RQS_IMAGE1:
    source1 = data.getData();
    textSource1.setText(source1.toString());
    break;
   case RQS_IMAGE2:
    source2 = data.getData();
    textSource2.setText(source2.toString());
    break;
   }
    
  }
 }

 private Bitmap ProcessingBitmap(){
  Bitmap bm1 = null;
  Bitmap bm2 =  null;
  Bitmap newBitmap = null;
  
  try {
   bm1 = BitmapFactory.decodeStream(
     getContentResolver().openInputStream(source1));
   bm2 = BitmapFactory.decodeStream(
     getContentResolver().openInputStream(source2));
   
   int w = bm1.getWidth() + bm2.getWidth();
   int h;
   if(bm1.getHeight() >= bm2.getHeight()){
    h = bm1.getHeight();
   }else{
    h = bm2.getHeight();
   }
   
   Config config = bm1.getConfig();
   if(config == null){
    config = Bitmap.Config.ARGB_8888;
   }
   
   newBitmap = Bitmap.createBitmap(w, h, config);
   Canvas newCanvas = new Canvas(newBitmap);
   
   newCanvas.drawBitmap(bm1, 0, 0, null);
   newCanvas.drawBitmap(bm2, bm1.getWidth(), 0, null);
   
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  return newBitmap;
 }
 

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"
        android:layout_gravity="center_horizontal"
        android:autoLink="web" />

    <Button
        android:id="@+id/loadimage1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />
    <TextView
        android:id="@+id/sourceuri1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/loadimage2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 2" />
    <TextView
        android:id="@+id/sourceuri2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/processing"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Processing" />
    <ImageView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
</LinearLayout>


download filesDownload the files.

Related:
- Merge two image, overlap with Alpha.




more: Something about processing images in Android

4 comments:

Unknown said...

Hi eric, I have a problem with your code
whenever I press the combine button to merge the image, the app stop working.
can you pls help mke?
I have an assigntment to do...

Jayson Fetra said...

Hi eric, I have a problem with your code
whenever I press the combine button to merge the image, the app stop working.
can you pls help mke?
I have an assigntment to do...

Erik said...

hello Jayson Fetra,

Any error message in logcat?
Are you going to load large image, and out of memory?

Unknown said...

No, processing button closes the application. It's not working at all. I have tried every sized photo.