Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is "Resources" in BitmapDrawable constructor really?

As the parameterless BitmapDrawableconstructor is deprecated, we have to give resource id to the constructor.

BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bmap);

Where res is generally getResources().

Why does the constructor need it and how can we define that value if we are using a general image cache?

like image 710
frankish Avatar asked Feb 17 '15 08:02

frankish


2 Answers

Why does the constructor need it?

From the docs of BitmapDrawable(Resources res, Bitmap bitmap):

Create drawable from a bitmap, setting initial target density based on the display metrics of the resources.

So, that is needed in order to set an initial target density using the display metrics, and the DisplayMetrics would be fetched from the Resources that you are providing as a parameter to BitmapDrawable.

How can we define that value if we are using a general image cache?

Sorry, cannot understand the question. Can you rephrase?

If I have already scaled the Bitmap myself, why does BitmapDrawable need resources?

How can BitmapDrawable know, that you have already scaled the Bitmap? Normally, if you are creating a BitmapDrawable you shouldn't take care of scaling it on your own, that's why the API is designed that way.

It seems like the only way to avoid scaling when converting a Bitmap to a Drawable is to use the deprecated constructor?

Although it sounds bad, but you can see how classes from transition framework use that constructor, e.g. ChangeBounds, Crossfade.

I've dug sources a bit and found out this chunk of code in Bitmap class:

static public int scaleFromDensity(int size, int sdensity, int tdensity) {
    if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
        return size;
    }

    // Scale by tdensity / sdensity, rounding up.
    return ((size * tdensity) + (sdensity >> 1)) / sdensity;
}

This is being called in following chain:

* BitmapDrawable#constructor
* BitmapDrawable#updateLocalState()
* BitmapDrawable#computeBitmapSize()
* Bitmap#getScaledWidth()
* scaleFromDensity(getWidth(), mDensity, targetDensity)

What if you explicitly set the density of your Bitmap to DENSITY_NONE? Then the if check will evaluate to true and no scaling would be performed.

Bitmap bitmap = ...
bitmap.setDensity(Bitmap.DENSITY_NONE);

Haven't tested, just making assumptions based on sources.

like image 177
azizbekian Avatar answered Nov 16 '22 01:11

azizbekian


In this constructor getResources() is needed "to set initial target density based on the display metrics of the resource". I understand it this way - you take the display metrics, that contain information about size, density, font scaling, and pass this info to constructor. Probably if you will have in your res/ folder image in different sizes - in appropriate sub folders, like drawable-ldpi, drawable-hdpi - you will get different information.

To use it in image cache, you need to pass a Context to it, and then invoke like this: Context ctx; ctx.getResources(); Hope that helps.

like image 43
Krzysztof Kacprzak Avatar answered Nov 16 '22 02:11

Krzysztof Kacprzak