如何将Drawable转换为Bitmap?

1093

我希望将某个特定的 Drawable 设为设备的壁纸,但所有的壁纸功能只接受 Bitmap。由于我的环境版本低于2.1,因此无法使用 WallpaperManager

此外,我的绘图对象是从网络下载而来的,而不是存储在 R.drawable 中的。


1
http://codingaffairs.blogspot.com/2016/06/how-to-convert-drawable-to-bitmap-in.html - Developine
1
https://dev59.com/NnA75IYBdhLWcg3w6Nr8#15555203 - Erfan Bagheri
22个回答

13

也许这对某些人有所帮助...

从PictureDrawable转换为Bitmap,使用:

private Bitmap pictureDrawableToBitmap(PictureDrawable pictureDrawable){ 
    Bitmap bmp = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888); 
    Canvas canvas = new Canvas(bmp); 
    canvas.drawPicture(pictureDrawable.getPicture()); 
    return bmp; 
}

...实现的方式如下:

Bitmap bmp = pictureDrawableToBitmap((PictureDrawable) drawable);

与Rob的答案一样,您需要特定类型的“Drawable”,在这种情况下是“PictureDrawable”。 - kabuko
4
也许这能帮到某个人... - Mauro

13

这里是@Chris.Jenkins提供的答案的 Kotlin 版本:https://dev59.com/NnA75IYBdhLWcg3w6Nr8#27543712

fun Drawable.toBitmap(): Bitmap {
  if (this is BitmapDrawable) {
    return bitmap
  }

  val width = if (bounds.isEmpty) intrinsicWidth else bounds.width()
  val height = if (bounds.isEmpty) intrinsicHeight else bounds.height()

  return Bitmap.createBitmap(width.nonZero(), height.nonZero(), Bitmap.Config.ARGB_8888).also {
    val canvas = Canvas(it)
    setBounds(0, 0, canvas.width, canvas.height)
    draw(canvas)
  }
}

private fun Int.nonZero() = if (this <= 0) 1 else this

12

这里有更好的分辨率。

public static Bitmap drawableToBitmap (Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable)drawable).getBitmap();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap); 
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

public static InputStream bitmapToInputStream(Bitmap bitmap) {
    int size = bitmap.getHeight() * bitmap.getRowBytes();
    ByteBuffer buffer = ByteBuffer.allocate(size);
    bitmap.copyPixelsToBuffer(buffer);
    return new ByteArrayInputStream(buffer.array());
}

如何将Drawable位读取为InputStream的代码中获取


12

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);

但如果您的drawable是层列表绘制,则此方法不会起作用并返回空响应,因此作为替代方案,您需要将可绘制对象绘制到画布上,然后保存为位图,请参考以下代码示例。

public void drawableToBitMap(Context context, int drawable, int widthPixels, int heightPixels) {
    try {
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/", "drawable.png");
        FileOutputStream fOut = new FileOutputStream(file);
        Drawable drw = ResourcesCompat.getDrawable(context.getResources(), drawable, null);
        if (drw != null) {
            convertToBitmap(drw, widthPixels, heightPixels).compress(Bitmap.CompressFormat.PNG, 100, fOut);
        }
        fOut.flush();
        fOut.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private Bitmap convertToBitmap(Drawable drawable, int widthPixels, int heightPixels) {
    Bitmap bitmap = Bitmap.createBitmap(widthPixels, heightPixels, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, widthPixels, heightPixels);
    drawable.draw(canvas);
    return bitmap;
}

以上代码将你的可绘制对象保存为 drawable.png 文件并存储在下载目录中。


在某些设备上,使用 BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher); 会出现 "skia -- Failed to create image decoder with message 'unimplemented'" 的错误提示,因此最好使用 ContextCompat.getDrawable() 方法获取 Drawable 对象,然后再转换成 Bitmap。 - Ezequiel Adrian

8

Android提供了一种不太直接的解决方案:BitmapDrawable。要获取位图,我们必须将资源id R.drawable.flower_pic 提供给BitmapDrawable,然后将其转换为Bitmap

Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.flower_pic)).getBitmap();

6
< p > < code > BitmapFactory.decodeResource() 方法会自动缩放位图,这可能导致您的位图模糊。如果要防止缩放,请按照以下步骤操作:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap source = BitmapFactory.decodeResource(context.getResources(),
                                             R.drawable.resource_name, options);

或者

InputStream is = context.getResources().openRawResource(R.drawable.resource_name)
bitmap = BitmapFactory.decodeStream(is);

5

使用这段代码,它将帮助您实现目标。

 Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.profileimage);
    if (bmp!=null) {
        Bitmap bitmap_round=getRoundedShape(bmp);
        if (bitmap_round!=null) {
            profileimage.setImageBitmap(bitmap_round);
        }
    }

  public Bitmap getRoundedShape(Bitmap scaleBitmapImage) {
    int targetWidth = 100;
    int targetHeight = 100;
    Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, 
            targetHeight,Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(targetBitmap);
    Path path = new Path();
    path.addCircle(((float) targetWidth - 1) / 2,
            ((float) targetHeight - 1) / 2,
            (Math.min(((float) targetWidth), 
                    ((float) targetHeight)) / 2),
                    Path.Direction.CCW);

    canvas.clipPath(path);
    Bitmap sourceBitmap = scaleBitmapImage;
    canvas.drawBitmap(sourceBitmap, 
            new Rect(0, 0, sourceBitmap.getWidth(),
                    sourceBitmap.getHeight()), 
                    new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG));
    return targetBitmap;
}

3
在Kotlin中,最简单的方法是:
Drawable.toBitmap(width: Int, height: Int, config: Bitmap.Config?): Bitmap

像这样:

val bitmapResult = yourDrawable.toBitmap(1,1,null)

在这里,只需要一个可绘制变量,不需要资源、上下文或ID。


您的扩展函数导致了一个 Function 'toBitmap' without a body must be abstract 的错误。 - hannes ach
@hannesach 你需要使用core-ktx依赖项来获取扩展功能。 - Nino DELCEY

2
如果您正在使用Kotlin,则使用下面的代码。它会起作用。
// 用于使用图像路径
val image = Drawable.createFromPath(path)
val bitmap = (image as BitmapDrawable).bitmap

2

ImageWorker库可以将位图转换为drawable或base64,反之亦然。

val bitmap: Bitmap? = ImageWorker.convert().drawableToBitmap(sourceDrawable)

实现

在项目级别的Gradle中

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

在应用层级Gradle中
dependencies {
            implementation 'com.github.1AboveAll:ImageWorker:0.51'
    }

你可以在外部存储和检索位图/可绘制的/base64图像。
请查看此处:https://github.com/1AboveAll/ImageWorker/edit/master/README.md

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