If you want to scale an image yourself, put a single copy in:
res/drawable-nodpi
Make sure that resource is in no other folders.
Load the bitmap like this:
Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(),
R.drawable.my_image
);
Resize it like this:
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
Then draw it to your canvas:
canvas.drawBitmap(bitmap, 0, 0, null);
That's the least you need to know to get the job done.
Additional notes
Normally, Android chooses your image from one of the res/drawable folders based on the current screen density.
Most image formats don't have density information, so Android makes assumptions about the density of the bitmap based on the folder it was loaded from.
That means it can do it's own scaling to match the density of the loaded bitmap with the canvas density.
Android checks and matches densities once when you load the bitmap, and again when you draw the bitmap.
When you are doing your own scaling you generally want to prevent the OS from interfering. There are several ways you can do it:
1. Use res/drawable-nodpi
This is the strategy I outlined in the quick example above. If you want to package your image as a resource, and still control the scaling yourself, put it here, and only here:
res/drawable-nodpi
If you need to support Cupcake, put a copy in each of these folders instead:
res/drawable-nodpi-v4
res/drawable
The decoder is automatically provided with options to prevent scaling. Android then sets the image density to to match the screen, so it won't scale when you draw it either. The compiler will apply lossless compression to images placed in res/drawable-xxx folders.
2. Use res/raw
You can leave the image untouched by the compiler if you put it in:
res/raw
But then you need to be careful to prevent scaling at runtime:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // Prevents scaling at decode time.
Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(),
R.raw.my_image,
options
);
bitmap.setDensity(Bitmap.DENSITY_NONE); // Prevents scaling at draw time.
3. Use the assets folder
If you put your images in the assets folder, instead of in res, you can use a real folder structure to organize them. Load a bitmap asset like this:
Bitmap bitmap = BitmapFactory.decodeStream(
context.getAssets().open(
"myfolder/my_image.png",
AssetManager.ACCESS_BUFFER
)
);
The compiler won't touch it, it loads without scaling, and it's density is set to match the screen, so it won't get scaled when you draw it either.
(PERFORMANCE NOTE: Before Android loads an image, it has to locate the file. A resource is faster to locate than an asset, so there may be some performance penalty if you package your images as assets.)