Android:如何叠加位图并在位图上绘制?

64

其实我有三个问题:

  1. 在绘制图像时,是在位图上绘制还是创建一个资源位图,然后在位图上绘制它,从性能方面来说哪一个更好?
  2. 如果我想在位图上绘制透明的东西,我该怎么做?
  3. 如果我想将一个透明的位图叠加在另一个位图上,我该怎么做?

很抱歉问题比较多,但为了学习的目的,我想探讨这两种方法。

7个回答

121

真不敢相信还没有人回答这个问题!在 Stack Overflow 上很少见!

1

我觉得这个问题有些不太清楚,但是我会尽力解答。如果你在问直接绘制到画布(多边形、阴影、文本等)与加载位图并将其拼贴到画布上之间的区别,这将取决于你的绘图复杂度。随着绘图越来越复杂,所需的 CPU 时间也会相应增加。但是,将位图拼贴到画布上始终是与位图大小成比例的常数时间。

2

如果我不知道“something”是什么,我怎么能告诉你如何做呢?你应该能够从第三个问题的答案中找到如何回答第二个问题。

3

假设:

  • bmp1 比 bmp2 大。
  • 你想要它们两个都从左上角重叠显示。

    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;
    }

@Declan Shanaghy,这个完美地运行了。你也可以使用drawBitmap(Bitmap bitmap,float left,float top,Paint paint)进行定位,请阅读此处的文档。 - sarfarazsajjad
我有900张图片想要叠加到其中...它可以完美地工作,但为什么它非常慢 :( 一次性处理需要很长时间。 - Ahmad Arslan
28
九百! :) - Fattie
如何从左下角开始绘制?@Declan - sagar suri

34

你可以像这样做:

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);
} 

这个想法非常简单:一旦将位图与画布关联起来,您可以调用任何画布的方法在位图上绘制。
这对具有透明度的位图有效。如果位图具有 alpha 通道,则该位图将具有透明度。查看Bitmap.Config。您可能希望使用 ARGB_8888。
重要提示:查看this Android 示例以了解不同的绘图方式。它会帮助您很多。
就性能而言(确切地说是内存方面),位图是最好的对象,因为它们只是包装本机位图。ImageView 是 View 的子类,BitmapDrawable 包含一个位图,但它还包含许多其他内容。但这是一种过度简化。您可以针对特定的性能场景提出建议,以获得精确的答案。

2
我有900张图片想要叠加到其中...它可以正常工作,但为什么速度非常慢 :( 它真的很耗时间。 - Ahmad Arslan
我遇到了IllegalArgumentException...它说是不可变位图。 - Rahul Rastogi
我知道这是一个旧评论,但是对于其他可能遇到此问题的人来说:bitmap参数需要是可变位图。请查看这篇博客文章,了解如何将不可变位图转换为可变位图或将文件加载到可变位图中。 - et_l

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;
}

3

如果目的是获取位图,这非常简单:

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

最终,图像将包含图像和图像2的重叠部分。

2
我认为这个例子可以帮助你在另一张图片上叠加一个透明的图片。这是通过在画布上绘制两个图像并返回位图图像实现的。
点击这里阅读更多或下载演示。
private Bitmap createSingleImageFromMultipleImages(Bitmap firstImage, Bitmap secondImage){

        Bitmap result = Bitmap.createBitmap(firstImage.getWidth(), firstImage.getHeight(), firstImage.getConfig());
        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(firstImage, 0f, 0f, null);
        canvas.drawBitmap(secondImage, 10, 10, null);
        return result;
    }

当点击按钮时,请调用上述函数,并将两个图像按照下面所示传递给我们的函数

public void buttonMerge(View view) {

        Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.drawable.img1);
        Bitmap smallImage = BitmapFactory.decodeResource(getResources(), R.drawable.img2);
        Bitmap mergedImages = createSingleImageFromMultipleImages(bigImage, smallImage);

        img.setImageBitmap(mergedImages);
    }

如果您需要合并两张以上的图片,可以参考这个链接:如何在安卓平台上使用程序合并多张图片


2

对于 Kotlin 粉丝:

  1. 您可以创建一个更通用的扩展:
 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
    }


然后按照以下方式使用它:
 bitmap.addOverlay( R.dimen.top_margin, R.dimen.left_margin, overlayBitmap)

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接