MERGE MULTIPLE IMAGES INTO ONE IMAGE IN ANDROID
Introduction:
This blog post is completely related to my previous post Splitting an image into smaller chunks. As far as the work is concerned both are responsible for completely opposite work. First one is responsible for splitting and this one is responsible for merging.
Where We Need This?
As I said in my previous post this kind of splitting and merging concept is very much essential for sending and receiving larger image files across the web.
My previous post will help you to send larger image files and this post will help you to merge the received image chunks to get the original one.
How To Achieve This?
We simply need to follow the following steps to achieve this.
- Get all the smaller image chunks.
- Find the width and height of those smaller images. (NOTE: all image chunks are of same size)
- Create a Bitmap with width = width_of_each_smaller_chunk * rows and height = height_of_each_smaller_chunk * columns.
- Create a Canvas encapsulating the Bitmap object in it.
- Now draw the smaller chunks on the Canvas object.
Source Code:
- chunkHeight & chunkWidth : Height and Width of smaller image chunks.
- smallImages : An ArrayList<Bitmap> object which stores all the smaller image chunks in their bitmap format.
- bitmap : The target bitmap which will represent the original image after merge.
- canvas : The canvas object encapsulating the target bitmap to draw the smaller image chunks.
You need to FOCUS more on the following line of code of onClick() method.
Source Code:
The below code snippet shows how to merge smaller image chunks into one.
package com.example.android.imagemerger;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
/**
*
* @author Chandra
Sekhar Nayak
* @version 1.0
*
* This class is an
activity and will displayed first when application starts
* This Activity will
display small images in a grid view
* It also shows a
button showing "Merge" on it. When clicks merges the small image
chunks
*/
public class SmallImagesActivity extends Activity implements
OnClickListener {
ArrayList<Bitmap> smallImages;
/** Called when
the activity is first created. */
@Override
public void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_grid);
/*
* This
application will for merging number of smaller chunks to make the original
* So for that
we need some smaller image chunks. As I don't have any smaller images,
* so I
programmatically first split an image to get the smaller image chunks
* and then
merge them to get the original one.
*
* If you want
you can also get some smaller chunks and directly merge them.
*
* The below 4
lines of code does the splitting operation
*/
ImageView
image = new ImageView(getApplicationContext());
image.setImageResource(R.drawable.katewinslet);
int chunkNumbers
= 25;
smallImages =
splitImage(image, chunkNumbers);
/*
* This code
is to show all the smaller image chunks into a grid structure
*/
GridView grid
= (GridView) findViewById(R.id.gridview);
grid.setAdapter(new
ImageAdapter(this, smallImages));
grid.setNumColumns(5);
/*
* This gets the
merge button and registers an click listener on it.
*/
Button mergeButton =
(Button) findViewById(R.id.merge_button);
mergeButton.setOnClickListener(this);
}
/**
* Splits the
source image and show them all into a grid in a new activity
*
* @param image
The source image to split
* @param
chunkNumbers The target number of small image chunks to be formed from the
source image
* @return
ArrayList<Bitmap> The resulted smaller image chunks in a List of Bitmaps
*/
private
ArrayList<Bitmap> splitImage(ImageView image, int chunkNumbers) {
//For the number of
rows and columns of the grid to be displayed
int rows, cols;
rows = cols = 5;
//For height and
width of the small image chunks
int chunkHeight,
chunkWidth;
//To store all the
small image chunks in bitmap format in this list
ArrayList<Bitmap> chunkedImages = new
ArrayList<Bitmap>(chunkNumbers);
//Getting the scaled
bitmap of the source image
BitmapDrawable
drawable = (BitmapDrawable) image.getDrawable();
Bitmap bitmap =
drawable.getBitmap();
Bitmap scaledBitmap
= Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(),
true);
rows = cols = (int)
Math.sqrt(chunkNumbers);
chunkHeight =
bitmap.getHeight()/rows;
chunkWidth =
bitmap.getWidth()/cols;
//xCoord and yCoord
are the pixel positions of the image chunks
int yCoord = 0;
for(int x=0;
x<rows; x++){
int xCoord = 0;
for(int y=0;
y<cols; y++){
chunkedImages.add(Bitmap.createBitmap(scaledBitmap, xCoord, yCoord,
chunkWidth, chunkHeight));
xCoord += chunkWidth;
}
yCoord +=
chunkHeight;
}
return
chunkedImages;
}
/*
* This method
actually implements the code for merging the small images
* @see
android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View
view) {
//Get the width and
height of the smaller chunks
int chunkWidth =
smallImages.get(0).getWidth();
int chunkHeight =
smallImages.get(0).getHeight();
//create a bitmap of
a size which can hold the complete image after merging
Bitmap bitmap =
Bitmap.createBitmap(chunkWidth * 5, chunkHeight * 5, Bitmap.Config.ARGB_4444);
//create a canvas
for drawing all those small images
Canvas canvas = new
Canvas(bitmap);
int count = 0;
for(int rows = 0;
rows < 5; rows++){
for(int cols = 0;
cols < 5; cols++){
canvas.drawBitmap(smallImages.get(count), chunkWidth * cols, chunkHeight
* rows, null);
count++;
}
}
/*
* The result image
is shown in a new Activity
*/
Intent intent = new
Intent(SmallImagesActivity.this, MergedImage.class);
intent.putExtra("merged_image", bitmap);
startActivity(intent);
}
}
Some Important points:
The 3rd argument of the createBitmap() method is the configuration for the Bitmap. I usedBitmap.Config.ARGB_4444. Documentation recommends ARGB_8888 instead of ARGB_4444. AsARGB_8888 will give you more qualitative image, so there is every chance of getting BINDER TRANSACTION FAILED error if your device configuration is low. So I used ARGB_4444, if you are not getting any error with ARGB_8888, ten better go for that. For more information about these configuration see this.
Reference:
You can download the complete source code from My Google Drive Account.
Screen Shots:
Source Images |
Result Image |
No comments:
Post a Comment