# How can I draw a small bitmap on a larger bitmap at a particular position? (Canvas / SurfaceView)

I'm building a game that requires additive blending of colours for certain bitmaps. Say I have 4 different types object, there are maybe ten of each type on the screen with each type having a distinct colour. If these objects overlap I want to perform additive blending on the overlapping portions. After doing some research on the subject I came across this thread about drawing and additive blending. It has lots of useful information, but it's not using bitmaps. Then I found another thread about blending pixels from two bitmaps which is also helpful, but is based on same sized bitmaps.

So my solutions to solve this problem is to create four temporary bitmaps, one for each object type / colour, with each of these bitmaps being the same size as the device screen. I want to draw all objects of each colour onto the relevant bitmap, so all the blue objects on one bitmap, all the orange objects on another and so on. Then when all for bitmaps are ready I'll perform additive blending on the four bitmaps of the same size as per the link above. then draw the result on the canvas.

My only problem is I'm not sure how to position the smaller bitmaps correctly on the larger one. Can anyone advise me on how I might proceed with this?

OK, my lack of understanding of Paint objects and how filtering works let me to make some incorrect assumptions about how straight forward this might be.

I have figured it out in the end anyway.

To do additive blending you need grey scale images that represent each channel of colour: alpha, red, green and blue.

Gimp has the functionality to separate images into these individual colour channels. Once separated, I add them to my project resources and, as suggested above, create temporary bitmaps the same size as the screen, a paint object and a canvas for each colour and the alpha channel. For each paint I add the corresponding grey scale image to a BitmapShader (with Mode set to CLAMP) and set it to the paint. I also add a new PorterDuffColorFilter to each paint set to the corresponding colour, and multiply mode. Here's what the red channel looks like:

    redPaint.setShader(new BitmapShader(redTempBmp, TileMode.CLAMP,
TileMode.CLAMP));
redPaint.setColorFilter(new PorterDuffColorFilter(Color.RED,
Mode.MULTIPLY));
redPaint.setXfermode(new PorterDuffXfermode(Mode.SCREEN));


For the alpha channel (after some research) I discovered bit shifting the colour pixels (from my grey scale alpha image) into the alpha channel will result in the correct alpha levels. I found a method online to do this. here's the code:

private Paint getAlphaBitmap(int width, int height, Bitmap alphaTempBmp) {

int pixelCount = width * height;
int[] alphaPixels = new int[pixelCount];
alphaTempBmp.getPixels(alphaPixels, 0, width, 0, 0, width, height);
for(int i = 0; i < pixelCount; i++){

alphaPixels[i] = alphaPixels[i] << 8;

}
alphaTempBmp.setPixels(alphaPixels, 0, width, 0, 0, width, height);
Paint alphaPaint = new Paint();
alphaPaint.setAntiAlias(true);
alphaPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
return alphaPaint;
}


From this point, in my draw method I can just draw 3 rectangles, each the size of the screen using the above paints to get the desired additive blending results. After that I draw the alphaBitmap on top and the job is done.

There is one more factor to take into consideration. When using software to split an image into separate channels, on the resulting alpha bitmap clear areas appear black. For my purposes this didn't work as I needed to draw the sprites onto the temp alpha bitmap in order to generate a screen sized alpha bitmap. This means if any images overlap then the black representing the clear parts of the image overwrite the coloured parts on the image beneath it. So, I drew my sprites as I wanted them, and rendered them in grey scale without any alpha channel. I then created the alpha channel separately and made sure it contained only white/grey without any black. The results work quite well. Now however, I have another problem - the code is quite slow, I hope multi-threading will sort the issue, otherwise I'm back to square 1.

EDIT: This is way to slow to use for any sort of animation. Needs to be applied using OpenGL.