setImageDrawable don't scale correctly with no resource images - android

I'm trying to load a image stored in filesystem into a imageButton. But it not scaling correctly. The file is the same (t700.png) in drawable resources and in filesystem, but the result is diferent.
This work fine:
button.setImageDrawable(getResources().getDrawable(R.drawable.t700));
This change scale / size and get bigger image:
String filePath = VideoActivity.this.getFilesDir()+File.separator+EPGApiService.LOGOS_DIR+File.separator+channel.getLogoFile();
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
BitmapDrawable imgDrawable = new BitmapDrawable( this.getResources(),bitmap);
button.setImageDrawable(imgDrawable);
I need same result..
NOTE:
if I do
BitmapDrawable logoBitmapDrawableFromDisk = new BitmapDrawable(VideoActivity.this.getResources(),logoBitmap);
BitmapDrawable logoBitmapDrawableFromDisk2 = new BitmapDrawable(logoBitmap);
BitmapDrawable logoBitmapDrawableFromRes = (BitmapDrawable) getResources().getDrawable(R.drawable.t700);
The Drawables Bitmaps sizes are not the same!
logoBitmapDrawableFromDisk size is 410x123
logoBitmapDrawableFromDisk2 size is 205x62
logoBitmapDrawableFromRes size is 820x246
The real file is the same. I need the same size on this two ways.

BitmapDrawable(getResources(), bitmap)
Create drawable from a bitmap, setting initial target density based on the display metrics of the resources.
It looks bigger because it is using the resource object to adjust the image to your screen's density.
To avoid that use BitmapDrawable(bitmap)
Or resize your png to look right in a mdpi device.
Then BitmapDrawable(getResources(), bitmap) will give you the correct look in all devices.
The correct way to have same look in all devices is create different icons for each device density.
Start with the dimension for mdpi density. The dimensions for each the other densities should be calculated based in the following values:
hdpi multiply by 1.5
xhdpi multiply by 2
xxhdpi multiply by 3
Each icon should be put under separate folders with the appropriate name depending on density:
mdpi -> res/drawable_mdpi
hdpi -> res/drawable_hdpi
xhdpi -> res/drawable_xhdpi
xxhdpi -> res/drawable_xxhdpi
Set the ImageButton source in xml or use getResources().getDrawable(R.drawable.t700); the device will automatically select the right one.
For more information see this

Related

Another bitmap's sizes

I added bitmap image to drawable folder with 64x64 sizes. Then I get a reference to this by Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.brick); The problem is in output I get an image with 128x128 sizes. I dont use any BitmapFactory.Options. Why it happens?
I added bitmap image to drawable folder with 64x64 sizes
I am going to assume that you mean this literally, and you put the images in res/drawable/. That is a synonym for res/drawable-mdpi/.
The problem is in output I get an image with 128x128 sizes.
That would occur if your device is an -xhdpi device. Android will resample the drawable from -mdpi (~160dpi) to -xhdpi (~320dpi).
Try moving your image to res/drawable-nodpi/.

getWidth() function in bitmap library of android doesn't return true image height

I wanted to load an .PNG image through my android application by using android.graphics.Bitmap library. I have succeeded to load it but there is some problem i can't figure out.
My image pixel count is 144*144 but when i try to get the width of my loaded image by using getWidth() function, it returns 432 which is 144*3.
This is how i try to load my image:
mBitmapIn = loadBitmap(R.drawable.data);
Where the loadBitmap function is defined as:
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeResource(getResources(), resource, options);
}
I would appreciate if anybody could help me to find out the reason of it.
Thanks
drawable folder is considered to have mdpi's density (which is the baseline density). Nexus 5 has a density of 445ppi which falls under xxhdpi category. Therefore if you read in a bitmap which is not present in drawable-xxhdpi directory, the system will have to find it in another directory and scale it. xxhdpi screens are approximately 3 times as dense as mdpi screens. Since the only drawable folder you have under res is drawable itself, android scales it 3 times along both the dimensions
You can get more information about this here

how to use drawable to compatible with all screen sizes (idpi, mdpi, hdpi, xhdpi, xxhdpi)

Hello I am new in android programing so I want to know:
How to use drawable to compatible with all screen sizes (idpi, mdpi, hdpi, xhdpi, xxhdpi)
Actually I am confused about drawable screen sizes compatibility with all screen sizes
so I want to know that:
If I want my app to compatible with all screen size do I need to put images in every drawable folder
for example: background image
• drawable-ldpi ( 240x320 for QVGA Device 2.7 ) put image with this
resolution
• drawable-mdpi ( 320x480 for HVGA Device 3.2 ) put image with this
resolution
• drawable-hdpi ( 480x800 for WVGA Device 4.0 ) put image with this
resolution
• drawable-xhdpi ( 1280x720 for WxVGA Device 4.7) put image with this
resolution
• drawable-xxhdpi ( 1080x1920 for Nexus 5 Device ) put image with
this resolution
or I can use a single same image for all screen sizes.
You do not need to create an image in every possible drawable folder. It's enough to provide one image only and put it into drawable folder. This image will be scaled automatically, depending on your usage.
This will not provide good quality on all screens though and may be more expensive to compute (scale). It is recommended that you can provide separate images for different screen densities (e.g. drawable-mdpi, drawable-hdpi, etc.) and the idea is that they should have different resolutions matching the screen densities.
Your images will only look sharp and crisp if you provide drawables for every dpi. Ldpi is no longer supported so you can ignore ldpi.
Also, for your launcher icon, provide an xxxhdpi image. Tablets running on Kit Kat with full hd screens use these images in the launcher.
Creating 1 drawable and putting it in the drawable folder is bad practice! Your images will look blurry.
I have got a very good method for this situation works like a charm. You only need to create one hd image for you and than method works-out everything.
Here is the method:
/**
* Get DRAWABLE with original size screen resolution independent
* #param is Input stream of the drawable
* #param fileName File name of the drawable
* #param density Density value of the drawable
* #param context Current application context
* #return Drawable rearranged with its original values for all
* different types of resolutions.
*/
public static Drawable getDrawable(InputStream is, String fileName, int density, Context context) {
Options opts = new BitmapFactory.Options();
opts.inDensity = density;
opts.inTargetDensity = context.getResources().getDisplayMetrics().densityDpi;
return Drawable.createFromResourceStream(context.getResources(), null, is, fileName, opts);
}
Here, you must prepare the inputstrem for your image file and set a density that is good for your screen at any usage area of yours. The smaller density is the lower quality, solve out by changing the value. Here are some examples on using the method:
1) Open an asset from the assets folder:
getDrawable(assetManager.open("image.png"), "any_title", 250, context)
2) Open a drawable from the drawables folder:
Here first, you must provide your inputstream with this method:
a) method:
/**
* Get InputStream from a drawable
* #param context Current application context
* #param drawableId Id of the file inside drawable folder
* #return InputStream of the given drawable
*/
public static ByteArrayInputStream getDrawableAsInputStream(Context context, int drawableId) {
Bitmap bitmap = ((BitmapDrawable)context.getResources().getDrawable(drawableId)).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] imageInByte = stream.toByteArray();
return new ByteArrayInputStream(imageInByte);
}
and the usage:
b) usage:
getDrawable(getDrawableAsInputStream(getBaseContext(), R.drawable.a_drawable), "any_title", 250, context)
I hope it is useful.
you have to create an image in several sizes. for example:
Let's say that you have ImageView with 48dp x 48dp.
Base on this size you have to create image with sizes:
48x48px(100% - mdpi)
64x64px(150% - hdpi)
96x96px(200% - xhdpi)
and so on, if you have to support more.
NOTE:
there is no need to create ldpi (75%) resolution image, because your hdpi will simply scale down twice.
If you use one size for several dpi, then there can be poor quality on some resolutions.
You can also use the Android Asset Studio, where you can upload an image and it will generate all of the types of resolution images you need. It can even be used to create animations and icons for your application. Here is the link:
https://romannurik.github.io/AndroidAssetStudio/index.html

Retrieve a Bitmap with a Fixed size

When you get a bitmap from a resource for example with:
Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.yourimage);
It is automatically scaled depending on the device's screen density. How can I avoid that and retrieve it in its original pixel size whatever the screen density is?
Thanks
What do you mean "It is automatically scaled"? When you call this method Android takes image from folder res/drawable-?dpi - depending on device where app is running. If your ldpi folder contains 30*30px image, mdpi contains 40*40px image and hdpi contains 60*60px, you will get bitmap one of this sizes(depends on device). Android does not change anything.
If you see that on the screen your image scaled somehow, check properties of ImageView.

Bitmap width/height different after loading from Resource

1st. i'am new to Android coding :)
What I do is I load an Bitmap from my res/drawable-mdpi with
BitmapFactory.decodeResource(getResources(), R.drawable.cat_ground_01);
after I Log out the width/height of the Bitmap it tells me an other value then the Bitmap realy is.
That's kinda difficult to place Bitmaps pixelperfect e.g. overlap a bitmap of an face with an bitmap of mouth.
maybe I'am just missing some knowledge for this Topic :9
I hope you can help.
When you do Bitmapfactory.decodeResource(), Android by default will choose the "matched" dpi version to decode, what happen in your mentioned code will yields:
You can't specify whether it is in mdpi, hdpi or whatever, it will choose the version that match your running System. i.e., if you are running on a mdpi device, it will decode the mdpi version; in ldpi, then the ldpi version.
Suppose you are using a hdpi device, but no mdpi resource is defined, what it will do is take your mdpi resource, and during decode, it will make it into hdpi (i.e., it enlarge your mdpi bitmap to about 1.5x larger); again, if your device has lower resolution then it will shrink the image
I guess this is what happens to you. For BitmapFactory, it actually has the option to NOT scaling the image:
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html
Set the inScaled to false will do.
Can't you just put the resource in the nodpi folder?
i.e. res/drawable-nodpi
This is what I've done in the past.
after I Log out the width/height of the Bitmap it tells me an other value then the Bitmap realy is.
Check your options.inTargetDensity and options.inDensity after loading the Bitmap from /drawable. They are not equal (160 and 240 for example). If options.inScaled set to true (default) - that's why the Bitmap is being automatically rescaled.
Another way is to use Bitmap.createScaledBitmap in order to rescale an image after loading. Because sometimes you need inScaled=true
//Target dimensions
int iW = 300;
int iH = 200;
Bitmap mOriginalBitmap = new Bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
//Load image from resource
mOriginalBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.sample_image_900px, options);
//Scale to target size
mOriginalBitmap = Bitmap.createScaledBitmap(mOriginalBitmap, iW, iH, true);

Categories

Resources