64

I have three questions actually:

  1. Is it better to draw an image on a bitmap or create a bitmap as resource and then draw it over a bitmap? Performance wise, which one is better?
  2. If I want to draw something transparent over a bitmap, how would I go about doing it?
  3. If I want to overlay one transparent bitmap over another, how would I do it?

Sorry for the long list, but in the interest of learning, I would like to explore both the approaches.

swimfar
  • 147
  • 6
Legend
  • 113,822
  • 119
  • 272
  • 400

6 Answers6

121

I can't believe no one has answered this yet! A rare occurrence on SO!

1

The question doesn't quite make sense to me. But I'll give it a stab. If you're asking about direct drawing to a canvas (polygons, shading, text etc...) vs. loading a bitmap and blitting it onto the canvas that would depend on the complexity of your drawing. As the drawing gets more complex the CPU time required will increase accordingly. However, blitting a bitmap onto a canvas will always be a constant time which is proportional to the size of the bitmap.

2

Without knowing what "something" is how can I show you how to do it? You should be able to figure out #2 from the answer for #3.

3

Assumptions:

  • bmp1 is larger than bmp2.
  • You want them both overlaid from the top left corner.

        private Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
            Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
            Canvas canvas = new Canvas(bmOverlay);
            canvas.drawBitmap(bmp1, new Matrix(), null);
            canvas.drawBitmap(bmp2, new Matrix(), null);
            return bmOverlay;
        }
    
swimfar
  • 147
  • 6
Declan Shanaghy
  • 2,314
  • 2
  • 18
  • 19
  • @Declan Shanaghy this is working perfect. you can also use drawBitmap(Bitmap bitmap, float left, float top, Paint paint) for positioning, read documentation [here](http://developer.android.com/reference/android/graphics/Canvas.html) – sarfarazsajjad Mar 15 '16 at 10:28
  • I have 900 images wanted to overlay images into it .. It works perfectly fine but why its very slow :( in one go its really time taking – Ahmad Arslan Jun 26 '16 at 13:59
  • 28
    NINE HUNDRED! :) – Fattie May 07 '17 at 17:45
  • How to start drawing from bottom left corner? @Declan – sagar suri Apr 06 '19 at 03:11
34

You can do something like this:

public void putOverlay(Bitmap bitmap, Bitmap overlay) {
    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
    canvas.drawBitmap(overlay, 0, 0, paint);
} 

The idea is very simple: Once you associate a bitmap with a canvas, you can call any of the canvas' methods to draw over the bitmap.

This will work for bitmaps that have transparency. A bitmap will have transparency, if it has an alpha channel. Look at Bitmap.Config. You'd probably want to use ARGB_8888.

Important: Look at this Android sample for the different ways you can perform drawing. It will help you a lot.

Performance wise (memory-wise, to be exact), Bitmaps are the best objects to use, since they simply wrap a native bitmap. An ImageView is a subclass of View, and a BitmapDrawable holds a Bitmap inside, but it holds many other things as well. But this is an over-simplification. You can suggest a performance-specific scenario for a precise answer.

Lior
  • 7,845
  • 2
  • 34
  • 34
  • 2
    I have 900 images wanted to overlay images into it .. It works perfectly fine but why its very slow :( its really time taking – Ahmad Arslan Apr 20 '15 at 06:08
  • I got IllegalArgumentException... It says immutable bitmap. – Rahul Rastogi May 08 '15 at 10:07
  • (I know - old comment. but for others who might come across it:) the `bitmap` parameter needs to be a mutable bitmap. Look at [this blog post](http://sudarnimalan.blogspot.co.il/2011/09/android-convert-immutable-bitmap-into.html) to see how to convert an immutable bitmap into a mutable one or to load a file into a mutable one. – et_l Jan 22 '17 at 08:36
17
public static Bitmap overlayBitmapToCenter(Bitmap bitmap1, Bitmap bitmap2) {
    int bitmap1Width = bitmap1.getWidth();
    int bitmap1Height = bitmap1.getHeight();
    int bitmap2Width = bitmap2.getWidth();
    int bitmap2Height = bitmap2.getHeight();

    float marginLeft = (float) (bitmap1Width * 0.5 - bitmap2Width * 0.5);
    float marginTop = (float) (bitmap1Height * 0.5 - bitmap2Height * 0.5);

    Bitmap overlayBitmap = Bitmap.createBitmap(bitmap1Width, bitmap1Height, bitmap1.getConfig());
    Canvas canvas = new Canvas(overlayBitmap);
    canvas.drawBitmap(bitmap1, new Matrix(), null);
    canvas.drawBitmap(bitmap2, marginLeft, marginTop, null);
    return overlayBitmap;
}
AnsonChen
  • 268
  • 3
  • 7
3

If the purpose is to obtain a bitmap, this is very simple:

Canvas canvas = new Canvas();
canvas.setBitmap(image);
canvas.drawBitmap(image2, new Matrix(), null);

In the end, image will contain the overlap of image and image2.

Giorgio Barchiesi
  • 6,109
  • 3
  • 32
  • 36
2

For Kotlin fans:

  1. U can create a more generic extension :
 private fun Bitmap.addOverlay(@DimenRes marginTop: Int, @DimenRes marginLeft: Int, overlay: Bitmap): Bitmap? {
        val bitmapWidth = this.width
        val bitmapHeight = this.height
        val marginLeft = shareBitmapWidth - overlay.width - resources.getDimension(marginLeft)
        val finalBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, this
            .config)

        val canvas = Canvas(finalBitmap)
        canvas.drawBitmap(this, Matrix(), null)
        canvas.drawBitmap(overlay, marginLeft, resources.getDimension(marginTop), null)
        return finalBitmap
    }

  1. Then use it as follow:
 bitmap.addOverlay( R.dimen.top_margin, R.dimen.left_margin, overlayBitmap)
Fab
  • 331
  • 2
  • 4
1
public static Bitmap createSingleImageFromMultipleImages(Bitmap firstImage, Bitmap secondImage, ImageView secondImageView){

    Bitmap result = Bitmap.createBitmap(firstImage.getWidth(), firstImage.getHeight(), firstImage.getConfig());
    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(firstImage, 0f, 0f, null);
    canvas.drawBitmap(secondImage, secondImageView.getX(), secondImageView.getY(), null);

    return result;
}
Svitlana
  • 2,938
  • 1
  • 29
  • 38