wesrobin wesrobin - 5 months ago 26
Android Question

Splitting and rejoining a bitmap

I am writing an Android app that processes large bitmaps, and need to split the bitmap into separate 'tiles' and process each tile individually before stiching them back together in the final bitmap.

Any clues on how to do this? I thought it would be simple enough using createBitmap() and specifying the smaller tiles in a couple of nested for loops, but it's not as easy as I thought, because setPixels does not work as I thought it would.

A complication I have is that the 'tiles' need to overlap where they are not at the edge of the bigger bitmap, since the processing needs to see a couple of extra pixels around the sides of the bitmaps. I get around this if there is no need to split the image by simply adding a couple of layers of black pixels around the edges of the image, but this won't work for the tiles as they need the information of the actual surrounding pixels or the processing will not work.

Are there any easier methods to doing this? If not, how do I go about doing it using setPixels and createBitmap?

My code so far:

Bitmap finalImg = Bitmap.createBitmap(sourceImage.getWidth(), sourceImage.getHeight(), Bitmap.Config.ARGB_8888); //Bitmap to store the final, processed image
Bitmap tile = null; //Temporary Bitmap to store tiles

int tileDiameter = 500; //Width and height of tiles
int borderWidth = 5; //Amount of pixel overlap from other tiles

for (int y = 0 ; y < sourceImage.getHeight() ; y += tileDiameter) {
for (int x = 0 ; x < sourceImage.getWidth() ; x += tileDiameter) {
if (x == 0) {
if (y == 0) {
tile = Bitmap.createBitmap(sourceImage, x, y, (tileDiameter + borderWidth), (tileDiameter + borderWidth));
}
else {
tile = Bitmap.createBitmap(sourceImage, x, (y - borderWidth), (tileDiameter + borderWidth), (tileDiameter + borderWidth));
}
}
else {
if (y == 0) {
tile = Bitmap.createBitmap(sourceImage, (x - borderWidth), y, (tileDiameter + borderWidth), (tileDiameter + borderWidth));
}
else {
tile = Bitmap.createBitmap(sourceImage, (x - borderWidth), (y - borderWidth), (tileDiameter + borderWidth), (tileDiameter + borderWidth));
}
}
processor.process(tile);
//I need to attach this (processed) tile to it's correct location in finalImg. How!??
}
}

Answer

You can use Canvas.drawBitmap to draw the processed tile back to the result bitmap. Use the function like this:

Canvas canvas = new Canvas(finalImg);
canvas.drawBitmap(tile,
                  null,
                  new Rect(x, y,
                           x + tileDiameter, y + tileDiameter),
                  null);

Also notice that you probably need to get a mutable copy of tile since the one you get from Bitmap.createBitmap is immutable.