972

I would like to set a certain Drawable as the device's wallpaper, but all wallpaper functions accept Bitmaps only. I cannot use WallpaperManager because I'm pre 2.1.

Also, my drawables are downloaded from the web and do not reside in R.drawable.

| improve this question | |

20 Answers 20

1307

This piece of code helps.

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

Here a version where the image gets downloaded.

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);
}
| improve this answer | |
  • 1
    i think you have the url values. then my edited answer should help. – Praveen Jun 14 '10 at 8:49
  • where does str_url come from? I couldn't find any Drawable function related to strings... thanks for your help. – Rob Jun 14 '10 at 9:08
  • 12
    I think I found something: if "draw" is the drawable I want to convert to a bitmap then: Bitmap bitmap = ((BitmapDrawable)draw).getBitmap(); does the trick! – Rob Jun 14 '10 at 9:29
  • 1
    @Rob : if your Drawable is a BitmapDrawable only. (which means that your Drawable is but a wrapper around a Bitmap, actually) – njzk2 May 28 '13 at 11:47
  • 2
    note: this causes massive java.lang.OutOfMemoryError with JPG's – Someone Somewhere Jun 21 '18 at 12:04
763
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;
}
| improve this answer | |
  • 44
    This looks like the only answer that would work for any kind of drawable and also has a quick solution for a drawable that is already a BitmapDrawable. +1 – Matt Wolfe Jun 6 '12 at 22:37
  • 1
    just one amendment: docs says about BitmapDrawable.getBitmap() that it may come back null. I say it may also come back already recycled. – kellogs Sep 1 '12 at 21:20
  • 17
    Watch out: getIntrinsicWidth() and getIntrinsicHieght() will return -1 if drawable is a solid color. – S.D. Oct 12 '12 at 13:51
  • 5
    So... another check for ColorDrawable, and we have a winner. Seriously, someone make this the accepted answer. – kaay Jan 14 '13 at 12:41
  • 2
    Contrary to the flagged answer, this answers the question. – njzk2 May 28 '13 at 11:49
216

This converts a BitmapDrawable to a Bitmap.

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
| improve this answer | |
  • 9
    is this really the best way? Surely the drawable could be of another type and this would throw a runtimeException? For example it could be a ninePatchDrawble...? – Dori Jun 9 '11 at 11:38
  • 4
    @Dori you could wrap the code in a conditional statement to check if it is indeed a BitmapDrawable before casting it: if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); } – Tony Chan Jul 9 '11 at 1:57
  • 374
    Can't believe the 64 upvotes? That code obviously only works if d already is a BitmapDrawable, in which case it's trivial to retrieve it as a bitmap... Will crash with ClassCastException in all other cases. – Matthias Nov 3 '11 at 16:12
  • 3
    @Matthias not to mention that.. the question itself, same author, has 100 votes :/ – quinestor Dec 18 '12 at 17:29
  • 2
    This is so specialized to a trivial case. – njzk2 May 28 '13 at 11:48
143

A Drawable can be drawn onto a Canvas, and a Canvas can be backed by a Bitmap:

(Updated to handle a quick conversion for BitmapDrawables and to ensure that the Bitmap created has a valid size)

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;
}
| improve this answer | |
48

METHOD 1 : Either you can directly convert to bitmap like this

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

METHOD 2 : You can even convert the resource into the drawable and from that you can get bitmap like this

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

For API > 22 getDrawable method moved to the ResourcesCompat class so for that you do something like this

Bitmap myLogo = ((BitmapDrawable) ResourcesCompat.getDrawable(context.getResources(), R.drawable.logo, null)).getBitmap();
| improve this answer | |
32

very simple

Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);
| improve this answer | |
17

android-ktx has Drawable.toBitmap method: https://android.github.io/android-ktx/core-ktx/androidx.graphics.drawable/android.graphics.drawable.-drawable/to-bitmap.html

From Kotlin

val bitmap = myDrawable.toBitmap()
| improve this answer | |
17

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);
| improve this answer | |
15

So after looking (and using) of the other answers, seems they all handling ColorDrawable and PaintDrawable badly. (Especially on lollipop) seemed that Shaders were tweaked so solid blocks of colors were not handled correctly.

I am using the following code now:

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

Unlike the others, if you call setBounds on the Drawable before asking to turn it into a bitmap, it will draw the bitmap at the correct size!

| improve this answer | |
  • Wouldn't setBounds ruin the previous bounds of the drawable? Isn't it better to store it and restore it afterwards? – android developer Apr 11 '15 at 17:43
  • @androiddeveloper, if the bounds have been set, we are just using those anyway. In some cases this is needed where no bounds have been set and has no intrinsic size (such as ColorDrawables in some cases). So width and height would be 0, we give the drawable 1x1 that way it actually draws something. I could be argued we could do a type check for ColorDrawable in those cases, but this works for 99% of cases. (You can modify it for your needs). – Chris.Jenkins Apr 11 '15 at 17:48
  • @Chris.Jenkins What if it doesn't have bounds , and now it will get new ones? I'd also like to ask another question: what's the best way to set the bitmap size (even for BitmapDrawable) that gets returned ? – android developer Apr 11 '15 at 17:49
  • 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. – Chris.Jenkins Apr 11 '15 at 17:53
  • 1
    mutate() would make a copy leaving the original drawable alone which would negate the issue of passing back in the original bounds. I am seldom to change the code based on those points. If your use case requires it add another answer. I suggest you create another question for the Bitmap scaling. – Chris.Jenkins Apr 11 '15 at 19:09
13

Maybe this will help someone...

From PictureDrawable to Bitmap, use:

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

... implemented as such:

Bitmap bmp = pictureDrawableToBitmap((PictureDrawable) drawable);
| improve this answer | |
11

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 How to read drawable bits as InputStream

| improve this answer | |
10

Here is the nice Kotlin version of the answer provided by @Chris.Jenkins here: 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
| improve this answer | |
8

Android provides a non straight foward solution: BitmapDrawable. To get the Bitmap , we'll have to provide the resource id R.drawable.flower_pic to the a BitmapDrawable and then cast it to a Bitmap.

Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.flower_pic)).getBitmap();
| improve this answer | |
8

The latest androidx core library (androidx.core:core-ktx:1.2.0) now has an extension function: Drawable.toBitmap(...) to convert a Drawable to a Bitmap.

| improve this answer | |
5

Use this code.it will help you for achieving your goal.

 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;
}
| improve this answer | |
3

BitmapFactory.decodeResource() automatically scales the bitmap, so your bitmap may turn out fuzzy. To prevent scaling, do this:

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

or

InputStream is = context.getResources().openRawResource(R.drawable.resource_name)
bitmap = BitmapFactory.decodeStream(is);
| improve this answer | |
2

if you are using kotlin the use below code. it'll work

// for using image path

val image = Drawable.createFromPath(path)
val bitmap = (image as BitmapDrawable).bitmap
| improve this answer | |
2

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

This will not work every time for example if your drawable is layer list drawable then it gives a null response, so as an alternative you need to draw your drawable into canvas then save as bitmap, please refer below a cup of code.

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

above code save you're drawable as drawable.png in the download directory

| improve this answer | |
1
 // 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);
        }
    }
}
| improve this answer | |
  • I think you read the question wrong. The question asks: how to get a bitmap from a drawable resource not system gallery – kc ochibili May 29 '14 at 11:30
1

ImageWorker Library can convert bitmap to drawable or base64 and vice versa.

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

Implementation

In Project Level Gradle

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

In Application Level Gradle

dependencies {
            implementation 'com.github.1AboveAll:ImageWorker:0.51'
    }

You can also store and retrieve bitmaps/drawables/base64 images from external.

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

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.