How can I get an image to a canvas in order to draw on that image?
Asked
Active
Viewed 1.9e+01k times
7 Answers
206
The good way to draw a Drawable on a canvas is not decoding it yourself but leaving it to the system to do so:
Drawable d = getResources().getDrawable(R.drawable.foobar, null);
d.setBounds(left, top, right, bottom);
d.draw(canvas);
This will work with all kinds of drawables, not only bitmaps. And it also means that you can re-use that same drawable again if only the size changes.

Gábor
- 9,466
- 3
- 65
- 79
-
How does one use an animation-list (multiple frames) for animation with the canvas approach? – RichieHH Jul 27 '14 at 14:53
-
1Very useful! At least when you need just a background picture with no rocket science involved! – Asim Jan 06 '15 at 01:31
-
@RichieHH I have my background on a SurfaceView (propably a waste) and that surface view is embedded in a Framelayout and that framelayout contains ImageViews which I then animate - maybe that's an option for you? – AgentKnopf Apr 27 '15 at 08:08
-
4getDrawable(id) is being deprecated, you should either use the ContextCompat call above, or the getDrawable(id, theme) call. https://developer.android.com/reference/android/content/res/Resources.html#getDrawable(int) – wblaschko Dec 02 '16 at 21:37
-
@Saveen: Are you sure? As far as I can remember, this is supposed to work from the earliest versions of Android. – Gábor Aug 18 '17 at 07:50
-
`setBounds(0, 0, width, height)` – vrgrg Feb 09 '21 at 13:10
40
You need to load your image as bitmap:
Resources res = getResources();
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.your_image);
Then make the bitmap mutable and create a canvas over it:
Canvas canvas = new Canvas(bitmap.copy(Bitmap.Config.ARGB_8888, true));
You then can draw on the canvas.

Konstantin Burov
- 68,980
- 16
- 115
- 93
-
What if my .png is big and it gets cut after being loaded? i.e. I don;t want to have it cropped. It can be bigger than the screen, then I will try to make it zoomable and movable. How may I do that? Thank you so so much! – Sibbs Gambling Jul 04 '13 at 08:52
-
1@perfectionm1ng look at using BitmapRegionDecoder. It allows partial loading for big images. So you should be able to load only the part of image you're rendering at the moment. – Konstantin Burov Jul 05 '13 at 01:55
-
I have the same problem I am using the code Canvas cs = new Canvas(bitmap); Resources res = getResources(); Bitmap bitmapx = BitmapFactory.decodeResource(res, R.drawable.overlay_good_full); Bitmap bitmapxx = BitmapFactory.decodeResource(res, R.drawable.overlay_bad_full); if(text.equals("Good")) { cs.drawBitmap(bitmapx, 0, 0, tPaint); } else { cs.drawBitmap(bitmapxx, 0, 0, tPaint); } – Ahmad Arslan Feb 10 '14 at 06:06
-
16
also you can use this way. it will change your big drawble fit to your canvas:
Resources res = getResources();
Bitmap bitmap = BitmapFactory.decodeResource(res, yourDrawable);
yourCanvas.drawBitmap(bitmap, 0, 0, yourPaint);

AzizAhmad
- 637
- 1
- 9
- 20
-
BitmapFactory class doesn't have method "BitmapFactory.decodeResource(Resource, Drawable);"... – Crisic Jan 11 '16 at 16:44
-
14
Drawable d = ContextCompat.getDrawable(context, R.drawable.***)
d.setBounds(left, top, right, bottom);
d.draw(canvas);

34m0
- 5,755
- 1
- 30
- 22
-
-
getDrawable(id) is being deprecated, you should either use the ContextCompat call above, or the getDrawable(id, theme) call. https://developer.android.com/reference/android/content/res/Resources.html#getDrawable(int) – wblaschko Dec 02 '16 at 21:36
-
1For me, it was necessary to use `setBounds`. Without it, nothing got displayed. – Feb 04 '17 at 18:30
8
try this
Bitmap mBitmap = Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter);
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}

Rohit Mandiwal
- 10,258
- 5
- 70
- 83
-
But if i use canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); it works and it load the saved image on the canvas, but at the same time undo and redo stop working, Check my code http://pastebin.com/cP9w6stm – AndroidDev May 02 '13 at 09:52
3
To preserve the aspect ratio of my vector drawable I did this (in Kotlin):
val drawable = resources.getDrawable(R.drawable.my_vector, null)
val aspectRatio = drawable.intrinsicWidth.toFloat() / drawable.intrinsicHeight
val desiredWidthInPx = 100
val derivedHeightInPx = (desiredWidthInPx / aspectRatio).toInt()
drawable.setBounds(0, 0, desiredWidthInPx, derivedHeightInPx)
drawable.draw(canvas)

Mahozad
- 18,032
- 13
- 118
- 133
2
package com.android.jigsawtest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurafaceClass extends SurfaceView implements
SurfaceHolder.Callback {
Bitmap mBitmap;
Paint paint =new Paint();
public SurafaceClass(Context context) {
super(context);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
// TODO Auto-generated constructor stub
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
}

user1140237
- 5,015
- 1
- 28
- 56