Android: How to overlay a bitmap and draw over a bitmap?
Asked Answered
N

6

66

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.

Nonanonage answered 8/10, 2009 at 20:34 Comment(0)
Z
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;
        }
    
Zabrina answered 18/2, 2010 at 8:33 Comment(4)
@Declan Shanaghy this is working perfect. you can also use drawBitmap(Bitmap bitmap, float left, float top, Paint paint) for positioning, read documentation hereFuze
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 takingGusty
NINE HUNDRED! :)Stowell
How to start drawing from bottom left corner? @DeclanSecundas
D
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.

Discovery answered 29/1, 2011 at 10:45 Comment(3)
I have 900 images wanted to overlay images into it .. It works perfectly fine but why its very slow :( its really time takingGusty
I got IllegalArgumentException... It says immutable bitmap.Unfolded
(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 to see how to convert an immutable bitmap into a mutable one or to load a file into a mutable one.Exum
J
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;
}
Journeyman answered 21/10, 2015 at 3:32 Comment(0)
S
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.

Signature answered 19/10, 2012 at 9:41 Comment(0)
I
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)
Istria answered 11/12, 2019 at 19:33 Comment(0)
B
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;
}
Brail answered 25/7, 2017 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.