Why does BitmapFactory.decodeResource scale my image?
Asked Answered
P

2

6

I have an image that is 120x120px located in my /res/drawable/ directory. This is the size required for all devices.

To load this Bitmap, I am using the following:

Bitmap tmpBmp = BitmapFactory.decodeResource(getResources(), R.drawable.myimage);

The issue is that when I measure tmpBmp, the size is 360x360px. I know how to scale this back down to the 120x120 that I need, but it is a waste of processing time, although minimal.

I am assuming that this has something to do with screen densities, since my resource is in a density-less directory.

What is the reason for decodeResource scaling my image? And how do I stop it from doing so?

Pacification answered 13/4, 2014 at 20:1 Comment(0)
S
17

The default drawable directory assumes that images need to be scaled from the default mdpi size. Put your images in drawable-nodpi if you want to disable resource scaling.

Do note that a 120x120px image, if displayed on the screen, will be 3x smaller on a xxhdpi device compared to a mdpi device (as there are three times as many pixels per inch).

Schnapp answered 13/4, 2014 at 20:13 Comment(3)
I am just using temporary graphics until I meet with a graphic designer, so I have just a couple static sized images for my device. I assumed that densityless did not scaling, I was unaware of the -nodpi directive.Pacification
Right, the drawable directory assumes you want the image the same physical size on all devices (i.e., scale it automatically) as that is almost always the correct thing to do (very rarely do you want the physical size of your graphics to depend on the density of the display) hence why that is the default and why -nodpi exists for the special cases.Schnapp
Awesome. Appreciate the help.Pacification
B
3

That's because the density of your screen and your image are different. Then if you do not specify Options system will do it for you. At the source of BitmapFactory you could see this:

public static Bitmap decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts) {

    if (opts == null) {
        opts = new Options();
    }

    if (opts.inDensity == 0 && value != null) {
        final int density = value.density;
        if (density == TypedValue.DENSITY_DEFAULT) {
            opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
        } else if (density != TypedValue.DENSITY_NONE) {
            opts.inDensity = density;
        }
    }

    if (opts.inTargetDensity == 0 && res != null) {
        opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
    }

    return decodeStream(is, pad, opts);
}

Therefore to prevent scaling you need to specify Options param with inScaled=false param. Or put your image to the res/drawable-nodpi folder.

Bodgie answered 13/4, 2014 at 20:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.