Image from resources is scaled properly but image

2019-08-30 18:10发布

问题:

I am running into a strange issue. I have multiple images in my Android project which I stored as .png files under res\drawable. I was able to easily extract the images at runtime and convert them to a bitmap like this:

Drawable d = getResources().getDrawable(R.drawable.imageId);
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();

This works great and the image gets scaled correctly no matter what screen density the device has. All my images are 200 pixels by 200 pixels and my image layout is configured as 200 dip x 200 dip.

Now, I have stored all images as blobs in an SQlite database due to scalability issues and I am extracting them at runtime and converting to a bitmap like this:

byte[] bb = cursor.getBlob(columnIndex);
Bitmap bitmap = BitmapFactory.decodeByteArray(bb, 0, bb.length);

The image displays fine if the screen density is standard 160 dip. But if the density is any less or more, the image doesn't scale and remains 200 pixels x 200 pixels for 160 dip. So basically, on a smaller screen (120 dip), the image takes more space than it should and on a larger screen (240 dip), it takes less space than it should.

Has anyone else run into this bizarre issue? Any explanation, workaround, solution will be really appreciated.

Thanks much in advance!

回答1:

Okay, I finally got it to work by using createScaledBitmap().

After creating a bitmap from the blob, I calculate the scaling factor and then calculate the new width and height. I then use those in the createScaledBitmap() function. Here's the code that works:

public static Bitmap getImageFromBlob(byte[] mBlob) 
{
    byte[] bb = mBlob;
    Bitmap b = BitmapFactory.decodeByteArray(bb, 0, bb.length); 
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int newWidth = b.getWidth()*metrics.densityDpi)/DisplayMetrics.DENSITY_DEFAULT;
    int newHeight = b.getHeight()*metrics.densityDpi)/DisplayMetrics.DENSITY_DEFAULT;
    return Bitmap.createScaledBitmap(b, newWidth, newHeight,  true);
}

This link provided the clue: difference between methods to scale a bitmap



回答2:

Use decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts) and in opts set inDesity to let say 160.



回答3:

Worked for me, see this. But I have to say, I think SQLite is doing it right, and the android drawable is incorrectly sized.