How to resize a bitmap image : Android - android

I want to increase size of image. i get image with this code BitmapFactory.decodeResource(getResources(), R.drawable.car);
But this image has different size on different screens, so i want to resize image according to screen size.

Of course you can scale:
Bitmap bm = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, filter);

Yes you can do this by using the following code snippets, the first section retrns the width and height of the current screen, the second section re-sizes the image.
// This will return the screen size in pixels
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
// Use this to bind and re-size the image
Bitmap car;
car = BitmapFactory.decodeResource(getResources(), R.drawable.car);
car = Bitmap.createScaledBitmap(car, width, height, true);

In android, one should store each resources in at least 3 formats, xhdpi, hdpi and mdpi
considering that you have stored a resource's copy in all the 3 formats at their respective folders.
res/drawable-mdpi/my_icon.png // bitmap for medium density
res/drawable-hdpi/my_icon.png // bitmap for high density
res/drawable-xhdpi/my_icon.png // bitmap for extra high density
The platform is enough smart to pick up right resources according to right screen size on its own.
I don't think you'll face any issues, if you have proper images in all 3 folders.
http://developer.android.com/guide/practices/screens_support.html

Look at http://square.github.io/picasso/ you can download, set where you want the image and resize it, just in one line. It also allows disk caching.

Related

Android screen - different densities, different sizes

I have read this article about supporting multiple screens.
So for supporting different densities you should put different drawable bitmaps into correct drawable folders. Then android should load correct image according to current screen density.
But if I understand it right, lets say you have some bitmap for low dpi (75x75px) and for medium dpi (100x100px). So on larger density, it will fill more pixels than on the smaller one. But result physicall size would be the same but on larger density it is more pixels than on the smaller one. Correct image will be used so there will be good quality across different dpis.
And what if I want to have on larger screens larger images?
Lets say that I want to fill specific part of the screen. For example I want to have an ImageView which will have size of 20% of the screens width. I use this code now:
BitmapDrawable drawable = (BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.some_bitmap, null);
float ratio = (float)drawable.getIntrinsicHeight()/drawable.getIntrinsicWidth();
ImageView img = (ImageView) findViewById(R.id.imageview);
img.getLayoutParams().width = (int)(DISPLAY.widthPixels*0.2f);
img.getLayoutParams().height = (int)(ratio*DISPLAY.widthPixels*0.2f);
so I get ratio because a do not want to "stretch" bitmap. Then I am getting screens width using DisplayMetrics and I am setting dimensions of some ImageView.
I have read I should not use "hard coded pixels" but this is universall across all dpis and all physicall sizes. And should I put different drawables for different densities now? Because I do not care about density now. I just fill certain space of the screen. I do not want to use dpi because it is the same aross screens sizes but I want to have it that larger screen larger bitmap would be so I do not want to have "empty" spaces on larger screens. Thanks for any advice.

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

Bitmap is not being scaled correctly because of density

I am loading a bitmap that is stored in the drawable-hdpi folder (with all the other images).
options.inScaled = false;
Bitmap rawBMP = BitmapFactory.decodeResource(res, resId, options);
Bitmap finalBMP = Bitmap.createScaledBitmap(rawBMP, reqWidth, reqHeight, true);
the original bitmap is 512x512, thats also the size of rawBMP if i set inScaled to false.
The final bitmap only works on a device with less that 512 (my S2 with 480). On devices with higher res the final bmp size is reported as it should be, but the visible part of that image is the original size. So createScaledBitmap is creating a big bitmap but does not scale the original upwards.
If i set inScaled to true, i receive a rawBMP with LESS than original size but then the final bitmap seems to work but as you can imagine the quality suffers as it more than doubles in size.
On a Galaxy 10 tablet :
inScaled true : 512 original, 341 rawBMP, final 800 (density 160) final image is visible across the entire screen (height)
inScaled false: 510 original, 512 rawBMP, final 800 (density 240) final image visible part is still 512, the rest is filled with transparent, there was absolutely no scaling here.
I dont understand this behaviour. If i have a bmp with 512 pixels and want to scale it to 800 pixels and then just draw those pixels to the screen 1:1
edit
For arguments sake lets say i need the bitmap scaled this way, the code is a bit more than just this snippet

setImageDrawable don't scale correctly with no resource images

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

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