相关文章推荐
曾经爱过的汉堡包  ·  PHP ...·  1 月前    · 
深沉的伏特加  ·  Download a blob with ...·  3 月前    · 
叛逆的感冒药  ·  Strings.Format(Object, ...·  10 月前    · 

如何将Drawable转换为位图?

1067 人关注

我想设置某个 Drawable 作为设备的墙纸,但所有墙纸功能只接受 Bitmap 。我不能使用 WallpaperManager ,因为我是2.1版本。

另外,我的绘图工具是从网上下载的,并不存在于 R.drawable 中。

android
bitmap
wallpaper
android-drawable
Rob
Rob
发布于 2010-06-14
22 个回答
Praveen
Praveen
发布于 2022-01-27
已采纳
0 人赞同

This piece of code helps.

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

这里有一个版本,图像被下载。

String name = c.getString(str_url);
URL url_value = new URL(name);
ImageView profile = (ImageView)v.findViewById(R.id.vdo_icon);
if (profile != null) {
    Bitmap mIcon1 =
        BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
    profile.setImageBitmap(mIcon1);
    
Rob
我想我找到了一些东西:如果 "draw "是我想转换为位图的drawable,那么。 Bitmap bitmap = ((BitmapDrawable)draw).getBitmap(); 就可以了!
@Rob : 如果你的Drawable只是一个BitmapDrawable。(这意味着你的Drawable不过是Bitmap的一个包装物,实际上)
注意:这将导致JPG的大量java.lang.OutOfMemoryError。
这是将资源解码为位图,它不会将Drawable转换为位图,而是从源头创建一个位图。
This does not work with svgs. BitmapFactory.decodeResource() return null
André
André
发布于 2022-01-27
0 人赞同
public static Bitmap drawableToBitmap (Drawable drawable) {
    Bitmap bitmap = null;
    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
    if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
    
这看起来是唯一一个对任何种类的drawable都有效的答案,而且对已经是BitmapDrawable的drawable也有一个快速解决方案。+1
只有一个修正:关于BitmapDrawable.getBitmap(),文档说它可能返回空值。我说它也可能返回已被回收。
S.D.
请注意。如果drawable是纯色的, getIntrinsicWidth() getIntrinsicHieght() 将返回-1。
kaay
那么......再检查一下ColorDrawable,我们就有了一个赢家。说真的,有人把这个答案作为公认的答案。
与被标记的答案相反,这回答了问题。
Rob
Rob
发布于 2022-01-27
0 人赞同

这将一个BitmapDrawable转换为一个Bitmap。

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
    
Dori
这真的是最好的方法吗?当然,drawable可以是另一种类型,这将抛出一个运行时异常?例如,它可以是一个9PatchDrawble...?
@Dori 你可以把代码包在一个条件语句中,在铸造之前检查它是否真的是 BitmapDrawable if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
mxk
不敢相信有64个支持率?这段代码显然只在 d 已经生效的情况下才有效。 is a BitmapDrawable ,在这种情况下,把它作为一个位图来检索是很容易的......在所有其他情况下,会因 ClassCastException 而崩溃。
quinestor
@Matthias 更不用说......这个问题本身,同一个作者,有100票:/
这是对一个微不足道的案例如此专门化。
kabuko
kabuko
发布于 2022-01-27
0 人赞同

一个 Drawable 可以画在一个 Canvas 上,而一个 Canvas 可以被一个 Bitmap 所支持。

(更新以处理 BitmapDrawable 的快速转换,并确保创建的 Bitmap 具有有效的尺寸)

public static Bitmap drawableToBitmap (Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable)drawable).getBitmap();
    int width = drawable.getIntrinsicWidth();
    width = width > 0 ? width : 1;
    int height = drawable.getIntrinsicHeight();
    height = height > 0 ? height : 1;
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap); 
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
    
如果drawable param为null会怎样?
这个方法不支持VectorDrawable
假设你得到一个非空的Drawable,为什么需要检查宽度和高度是否为0?另外,如果它们的尺寸相同,为什么需要使用setBounds()?
好的解决方案!Android 8.0 /sdk 26 ApplicationInfo.loadIcon(PackageManager pm) 返回一个AdaptiveIconDrawable。 使用你的代码可以帮助我将AdaptiveIconDrawable投到位图。
Keyur Lakhani
Keyur Lakhani
发布于 2022-01-27
0 人赞同

METHOD 1 :要么你可以直接转换为位图,像这样

Bitmap myLogo = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_drawable);

METHOD 2:你甚至可以将资源转换为可画图,并从中获得像这样的位图

Bitmap myLogo = ((BitmapDrawable)getResources().getDrawable(R.drawable.logo)).getBitmap();

For API > 22 替换代码2】的方法被移到了ResourcesCompat类中,所以你要做这样的事情

Bitmap myLogo = ((BitmapDrawable) ResourcesCompat.getDrawable(context.getResources(), R.drawable.logo, null)).getBitmap();
    
ResourcesCompat只有在drawable是BitmapDrawable时才起作用,如果你使用的是VectorDrawable,那么你将会有一个CCE。
这两种方法都不能与 VectorDrawable resource. The following error occurs - android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
This solution works well with Kotlin.
MyDogTom
MyDogTom
发布于 2022-01-27
0 人赞同

android-ktx有 Drawable.toBitmap 方法。 https://android.github.io/android-ktx/core-ktx/androidx.graphics.drawable/android.graphics.drawable.-drawable/to-bitmap.html

From Kotlin

val bitmap = myDrawable.toBitmap()
    
这是Kotlin中最简单的 VectorDrawable 的解决方案!还分享了 in this SO post here 更加详细地介绍。
我从这个方法得到一个空白的位图。
Sanjayrajsinh
Sanjayrajsinh
发布于 2022-01-27
0 人赞同

1) Drawable to Bitmap :

Bitmap mIcon = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon);
// mImageView.setImageBitmap(mIcon);

2) Bitmap to Drawable :

Drawable mDrawable = new BitmapDrawable(getResources(), bitmap);
// mImageView.setDrawable(mDrawable);
    
问题明确指出drawable不在R.drawable中,而你的解决方案是针对R.drawable。
Erfan Bagheri
Erfan Bagheri
发布于 2022-01-27
0 人赞同

very simple

Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);
    
这只是剽窃了 其他答案 关于这个问题,早在整整三年前
Balazs Banyai
Balazs Banyai
发布于 2022-01-27
0 人赞同

最新的androidx核心库(androidx.core:core-ktx:1.2.0)现在有一个 extension function: Drawable.toBitmap(...) 将一个Drawable转换为一个Bitmap。

我不太明白如何导入该函数。我想它在Kotlin之外也能工作吧?
从java中,你需要导入包含扩展方法的Kt文件。另外,签名要稍微复杂一些,因为接收器和默认参数在java中是不可用的。它将是这样的。【替换代码0
Chris.Jenkins
Chris.Jenkins
发布于 2022-01-27
0 人赞同

所以在看了(和使用了)其他答案后,似乎他们都把 ColorDrawable PaintDrawable 处理得很糟糕。(特别是在棒棒糖上)似乎 Shader 被调整了,所以实心的色块没有被正确处理。

我现在使用的是以下代码。

public static Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    // We ask for the bounds if they have been set as they would be most
    // correct, then we check we are  > 0
    final int width = !drawable.getBounds().isEmpty() ?
            drawable.getBounds().width() : drawable.getIntrinsicWidth();
    final int height = !drawable.getBounds().isEmpty() ?
            drawable.getBounds().height() : drawable.getIntrinsicHeight();
    // Now we check we are > 0
    final Bitmap bitmap = Bitmap.createBitmap(width <= 0 ? 1 : width, height <= 0 ? 1 : height,
            Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;

与其他不同的是,如果你在要求将其变成位图之前,在setBounds上调用Drawable,它将以正确的尺寸绘制位图!

setBounds不是会毁掉drawable之前的边界吗?存储它并在之后恢复它不是更好吗?
@androiddeveloper,如果边界已经设置好了,我们反正就是使用这些边界。在某些情况下,需要这样做,因为没有设置边界,也没有固有的尺寸(比如某些情况下的ColorDrawables)。所以宽度和高度都是0,我们给drawable 1x1,这样它就能真正画出东西。我可以说,在这些情况下,我们可以对ColorDrawable做一个类型检查,但这对99%的情况都是有效的。(你可以根据你的需要修改它)。
@Chris.Jenkins 如果它没有边界,现在会得到新的边界怎么办?我还想问另一个问题:设置返回的位图大小(即使是BitmapDrawable)的最佳方法是什么?
I suggest you carefully read the code. If the Drawable does not have bounds set it uses the IntrinsicWidth/Height . If they are both <= 0 we set the canvas to 1px. You are correct if the Drawable does not have bounds it will be passed some (1x1 is most cases), but this is REQUIRED for things like ColorDrawable which DO NOT have intrinsic sizes. If we didn't do this, it would throw an Exception , you can't draw 0x0 to a canvas.
替换代码0】会产生一个拷贝,而不去管原始的drawable,这就否定了在原始边界上传递回的问题。我很少根据这些要点来改变代码。如果你的用例需要的话,可以添加另一个答案。我建议你为位图缩放创建另一个问题。
Mauro
Mauro
发布于 2022-01-27
0 人赞同

也许这将帮助某人...

从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);
    
与罗伯的答案一样,你需要一种特定类型的 Drawable ,在这种情况下是 PictureDrawable
"也许这将帮助某人......"
tasomaniac
tasomaniac
发布于 2022-01-27
0 人赞同

下面是@Chris.Jenkins在这里提供的漂亮的Kotlin版本的答案。 https://stackoverflow.com/a/27543712/1016462

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
    
Gelldur
Gelldur
发布于 2022-01-27
0 人赞同

Here is better resolution

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

Code from 如何以InputStream的形式读取drawable bit

Kishan Donga
Kishan Donga
发布于 2022-01-27
0 人赞同

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

这不是每次都能成功的,例如,如果你的可画性是图层列表可画性,那么它就会给出一个空的响应,所以作为一个替代方法,你需要把你的可画性画到画布上,然后保存为位图,请参考下面的一杯代码。

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。

kc ochibili
kc ochibili
发布于 2022-01-27
0 人赞同

安卓系统提供了一个非直接的解决方案。 BitmapDrawable 。为了得到Bitmap,我们必须向 BitmapDrawable 提供资源ID R.drawable.flower_pic ,然后将其投给 Bitmap

Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.flower_pic)).getBitmap();
    
John Doe
John Doe
发布于 2022-01-27
0 人赞同

替换代码0】会自动缩放位图,所以你的位图可能会变得模糊不清。为了防止缩放,请这样做。

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);
    
anupam sharma
anupam sharma
发布于 2022-01-27
0 人赞同

使用这个代码。它将帮助你实现你的目标。

 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;
    
Himanshu Rawat
Himanshu Rawat
发布于 2022-01-27
0 人赞同

ImageWorker Library可以将位图转换成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图像。

Check here. https://github.com/1AboveAll/ImageWorker/edit/master/README.md

0 人赞同

如果你使用kotlin,使用下面的代码。

//用于使用图像路径

val image = Drawable.createFromPath(path)
val bitmap = (image as BitmapDrawable).bitmap
    
Mori
Mori
发布于 2022-01-27
0 人赞同

In Kotlin ,最简单的方法是。

Drawable.toBitmap(width: Int, height: Int, config: Bitmap.Config?): Bitmap

like this:

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

其中,只需要一个可画的变量,没有资源,没有背景,没有ID

Angel
Angel
发布于 2022-01-27
0 人赞同
 // get image path from gallery
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
    super.onActivityResult(requestCode, resultcode, intent);
    if (requestCode == 1) {
        if (intent != null && resultcode == RESULT_OK) {             
            Uri selectedImage = intent.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            filePath = cursor.getString(columnIndex);
            //display image using BitmapFactory
            cursor.close(); bmp = BitmapFactory.decodeFile(filepath); 
            iv.setBackgroundResource(0);
            iv.setImageBitmap(bmp);
    
我认为你读错了问题。这个问题问的是:如何从可画资源而不是系统图库中获得位图。
Alberto
Alberto
发布于 2022-01-27
0 人赞同

我在这个主题上使用了一些答案,但有些答案没有达到预期的效果(也许它们在旧版本中曾起过作用),但我想在经过几次尝试和错误后分享我的答案,使用了一个扩展函数。

val markerOption = MarkerOptions().apply {
    position(LatLng(driver.lat, driver.lng))
    icon(R.drawabel.your_drawable.toBitmapDescriptor(context))
    snippet(driver.driverId.toString())
mMap.addMarker(markerOption)

This is the extension function:

fun Int.toBitmapDescriptor(context: Context): BitmapDescriptor {
    val vectorDrawable = ResourcesCompat.getDrawable(context.resources, this, context.theme)
    val bitmap = vectorDrawable?.toBitmap(
        vectorDrawable.intrinsicWidth,
        vectorDrawable.intrinsicHeight,