bitmap
resource
Android development
programming tutorial
image handling

How to set a bitmap from resource

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Loading an image from res/drawable into a Bitmap is straightforward in Android, but the correct approach depends on what you plan to do with that image. If you only want to display it, an ImageView can often use the drawable directly. If you need pixel access, resizing, or custom drawing, decoding a bitmap from resources is the right tool.

Decode a Bitmap from Resources

The basic API is BitmapFactory.decodeResource(). It takes a Resources instance and the drawable resource ID, then returns a Bitmap.

kotlin
1import android.graphics.Bitmap
2import android.graphics.BitmapFactory
3import android.os.Bundle
4import android.widget.ImageView
5import androidx.appcompat.app.AppCompatActivity
6
7class MainActivity : AppCompatActivity() {
8    override fun onCreate(savedInstanceState: Bundle?) {
9        super.onCreate(savedInstanceState)
10        setContentView(R.layout.activity_main)
11
12        val imageView = findViewById<ImageView>(R.id.previewImage)
13        val bitmap: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.sample_photo)
14        imageView.setImageBitmap(bitmap)
15    }
16}

That is enough for small images and quick prototypes. The problem is that decodeResource() loads the full image into memory. If the source image is large, that can waste memory or trigger OutOfMemoryError on older or lower-end devices.

Downsample Large Images

If the source asset is much larger than the target view, decode a smaller version. Android lets you inspect image bounds without allocating pixel memory, then choose an inSampleSize.

kotlin
1import android.graphics.Bitmap
2import android.graphics.BitmapFactory
3
4fun decodeScaledBitmap(reqWidth: Int, reqHeight: Int): Bitmap {
5    val options = BitmapFactory.Options().apply {
6        inJustDecodeBounds = true
7    }
8
9    BitmapFactory.decodeResource(MyApp.instance.resources, R.drawable.sample_photo, options)
10
11    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
12    options.inJustDecodeBounds = false
13
14    return BitmapFactory.decodeResource(
15        MyApp.instance.resources,
16        R.drawable.sample_photo,
17        options
18    )
19}
20
21fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
22    val height = options.outHeight
23    val width = options.outWidth
24    var sampleSize = 1
25
26    while (height / sampleSize > reqHeight * 2 || width / sampleSize > reqWidth * 2) {
27        sampleSize *= 2
28    }
29
30    return sampleSize
31}

This pattern is useful when you are decoding photos for thumbnails, cards, or full-screen previews. You still get a Bitmap, but now it is closer to the size the UI actually needs.

Choose the Right API for the Job

There are three common cases:

  1. Display only: call imageView.setImageResource(R.drawable.sample_photo) and skip manual bitmap work.
  2. Display with transformation: decode a bitmap, resize or crop it, then set it on the ImageView.
  3. Pixel-level processing: decode a mutable bitmap and draw on a Canvas or inspect individual pixels.

If you need a mutable bitmap for drawing, make a copy in a writable config:

kotlin
val original = BitmapFactory.decodeResource(resources, R.drawable.sample_photo)
val mutableBitmap = original.copy(Bitmap.Config.ARGB_8888, true)

That lets you draw overlays, watermarks, or annotations:

kotlin
1import android.graphics.Canvas
2import android.graphics.Color
3import android.graphics.Paint
4
5val canvas = Canvas(mutableBitmap)
6val paint = Paint().apply {
7    color = Color.RED
8    textSize = 48f
9}
10
11canvas.drawText("Preview", 32f, 64f, paint)

Resource Placement and Format

Put raster images in res/drawable, drawable-hdpi, drawable-xhdpi, and similar density-aware folders when appropriate. Android picks the closest resource for the current screen density, which improves sharpness and reduces unnecessary scaling.

For icons and simple illustrations, vector drawables are often better than bitmaps because they scale cleanly and usually consume less space. Use bitmaps when the source is photographic or when your code needs raw pixels.

Common Pitfalls

The biggest mistake is decoding a huge resource at full size just to show it in a small view. That wastes memory and can make scrolling or screen transitions stutter. Use BitmapFactory.Options and sample the image down.

Another issue is decoding on the main thread when the image is large. For simple resources this is fine, but large decodes should happen off the UI thread or through an image-loading library.

Developers also sometimes use Bitmap when a drawable would do. If all you need is display, setImageResource() is simpler and gives the framework more flexibility.

Finally, be careful when holding long-lived bitmap references in activities, adapters, or singletons. Large images can keep memory alive long after the screen should have released it.

Summary

  • Use BitmapFactory.decodeResource() when you need a real Bitmap from an Android resource.
  • For plain display, setImageResource() is often the simpler choice.
  • Large images should be downsampled with BitmapFactory.Options to avoid memory waste.
  • Mutable bitmaps are useful when you need to draw or edit pixels.
  • Choose bitmaps for photos and pixel work, and vector drawables for scalable artwork.

Course illustration
Course illustration

All Rights Reserved.