Android scaling of images to screen density - android

I have an application with an embedded drawable 48x48 pixel at 71,12 pixels/inch
I load the same image via a stream to a webserver, then load that stream
return new BitmapDrawable(getActivity().getResources(), new ByteArrayInputStream(imageThumbnail));
the displayed result is:
How can i get the BitmapDrawable to scale the same as the rest of the drawables?

you can trigger android bitmapfactory to scale bitmap automatically, codes for this:
BitmapFactory.Options options = new BitmapFactory.Options();
DisplayMetrics metrics = context.getApplicationContext().getResources().getDisplayMetrics();
options.inScreenDensity = metrics.densityDpi;
options.inTargetDensity = metrics.densityDpi;
options.inDensity = DisplayMetrics.DENSITY_DEFAULT;
Bitmap bm = BitmapFactory.decodeStream(in, null, options);
in.close();
BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), bm);

Do something like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Bitmap bitmapOrg = new BitmapDrawable(getResources(), new ByteArrayInputStream(imageThumbnail)).getBitmap();
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
float scaleWidth = metrics.scaledDensity;
float scaleHeight = metrics.scaledDensity;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true);
Or
Maybe try a differnet approach... try setting the height and width of images in the XML layout in dips, I am guessing you have the ImageView with wrap_content height and width at the moment, try setting the height and width to 48dip

Get the current density of the screen and set the drawable to that density
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int density = metrics.densityDpi
myDrawable.setDensity(densityDpi);

Related

Scaling bitmaps for each resolution

Is there any method that gets the phones resolution (or dp) and scales bitmaps accordingly? I have all my images in xhdpi folder and at the moment they do not scale the way they should.
I want an efficiant and memory-friendly method that can do the scaling automatically. If not, what is the next best thing? completely new area for me. So any tutorial-link is also appriciated.
this is what I use to load bitmaps atm:
public Bitmap loadBitmap(int resourceID) {
Options options = new BitmapFactory.Options();
options.inScaled = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap tempBmp = null;
try {
tempBmp = BitmapFactory.decodeResource(getResources(), resourceID,
options);
} catch (OutOfMemoryError e) {
} catch (Error e) {
}
return tempBmp;
}
If you wanna scale bitmap for each phone resolution, you should know phone screen size, scale ratio.
This code will return width (w) & height (h) of screen.
DisplayMetrics dMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dMetrics);
float density = dMetrics.density;
int w = Math.round(dMetrics.widthPixels / density);
int h = Math.round(dMetrics.heightPixels / density);
activity is instance of Activity which would you like to get screen size.
You have to remember that: When your device is in landscape orientation, w > h. When it in portrait orientation w < h.
So from width & height you can detect your device is in what orientation.
Example:
From w & h of device and ratio (which you want to scale) you can calculate new bitmap size to scale it.
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}

Image Quality distort when minimize the height and width of bitmap

I have a bitmap downloaded from internet and now i want to decrease the height and width of bitmap without losing the quality of bitmap. How to achieve this.
This is way for downloading bitmap from internet.
URL url_1 = null;
try {
url_1 = new URL(vmImageUrl);
bmp = BitmapFactory.decodeStream(url_1.openConnection().getInputStream());
} catch (Exception e) {
Log.v("Error while downloading bitmap from url", e.getMessage());
I have scaled like this.
Bitmap.createScaledBitmap(bmp, convertDpToPixel(140, context), convertDpToPixel(35, context), false);
This method convets dp unit to equivalent device specific value in pixels.
public static int convertDpToPixel(float dp,Context context)
{
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
int px = (int) (dp * (metrics.densityDpi/160f));
return px;
}
Use BitmapFactory.Options.inSampleSize to get a smaller bitmap.
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(YOUR_FILE, opts);
I set this.
Bitmap.createScaledBitmap(bmp, convertDpToPixel(140, context), VirtualMirrorActivity.convertDpToPixel(35, context), true);
instead of
Bitmap.createScaledBitmap(bmp, convertDpToPixel(140, context), VirtualMirrorActivity.convertDpToPixel(35, context), false);
Its give smoother edges & clear of bitmap. Now its working fine..
you need 2 Rect,
Rect src = new Rect();
Rect dst = new Rect();
then u can set the src for the current image,
src.set(0,0,imgWidth,imgHeigth);
then then the required size
dst.set(startX,startY,endX,endY);
Note: startX and startY will be the destination coordinates on the screen
and ur image will be drawn u to the endX endY coordinate.
and draw ur bit man with Canvas
Canvas.drawBitmap(bitmapFile, src, dst, null);

Set wallpaper in Android

I have image 640*480 in sd card and i want to set it as home screen wallpaper. How Can I do this with small quality loss? With my code Wallpaper has a not good clarity. That's my code:
private void setWallpaper(String filePath) throws IOException{
if(filePath!=null){
// set options for decoding
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDither = false;
options.inJustDecodeBounds = true;
//get bitmap from filepath
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
//get sizes of bitmap
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//get sizes of screen and scale level
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int newWidth = display.getWidth()*2;
int newHeight = display.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
//set matrix of the scaling
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
//get new bitmap for wallpaper
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
width, height, matrix, true);
//set bitmap as wallpaper
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
wallpaperManager.clear();
wallpaperManager.setBitmap(resizedBitmap);
}
}
Any time you scale upwards you're going to suffer quality loss. What size screen are you trying to display this image one? Keep in mind the Android wallpaper dimensions are the height of the screen by 2 times the width of the screen (e.g. 800x480 screen needs a 800x960 image).
My recommendation would be to have a larger image and scale downwards. The quality loss from downsampling is far less noticeable than from upscaling. You could, if space is not an issue, include multiple sizes of the image for differing screen resolutions.

Android: Resizing and scaling a part of the image

Given an image, I want to be able to scale only a part of that image. Say, I want to expand half of the image so that, that half takes up the whole space.
How is this possible?
Will ImageView fitXY work because I thought it'll work only for the whole original image.
#Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout linearLayout = new LinearLayout(this);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = 640;
int newHeight = 480;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// create the new Bitmap object
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 50, 50, width,
height, matrix, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
ImageView imageView = new ImageView(this);
imageView.setImageDrawable(bmd);
imageView.setScaleType(ScaleType.CENTER);
linearLayout.addView(imageView, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
setContentView(linearLayout);
}
}
This works only if in createBitmap, the X and Y coordinates of the first pixels in the source are 0. meaning, I'm not able to take a subset of the image. Only able to scale the whole image. But createBitmap is meant to subset an image.
In the log, when the parameters are not 0, I get the following exception: java.lang.IllegalArgumentException: x + width must be <= bitmap.width()
Please help
First you have to create a new bitmap with the part you want to scale using
createBitmap() //pass the source bitmap, req height and width
Now from the result bitmap, you have to create your scaled bitmap using
createScaledbitmap() //pass the result bitmap , req width, height
For exapmle:
Bitmap originalBitmap = BitmapFactory.decodeResource(res, id);
Bitmap partImage = originalBitmap.createBitmap(width, height, config);
Bitmap scaledImage = partImage.createScaledBitmap(partImage, dstWidth, dstHeight, filter);
So I had to fix a couple of Typos, but this example did a good job for me.http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
typos:
int width = bitmapOrg.width();
int height = bitmapOrg.height();
become:
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
otherwise, worked when I tried it agains SDK 7

android drawable changes sizes on screen when reading image from file

I have an image on a private file.
I read the file, create the drawable, and assign it to an ImageView.
The ImageView has WRAP_CONTENT so the size is automatic.
On 320x480 screens, the image looks good
But on screens with more resolution and high density 480x800 or 480x854 (N1, droid) , when the image is for example 150x150, I see the image as 100x100.
Of course it has something to do with the density but not sure how should I resolve this.
This is my code:
FileInputStream fis = this.openFileInput("icon.png");
icon = Drawable.createFromStream(fis, "icon");
fis.close();
imageView.setImageDrawable(icon);
thanks
================================================================
update:
with the following code:
FileInputStream fis = this.openFileInput("icon.png");
icon = Drawable.createFromStream(fis, "icon");
if I then inspect the size of the icon, android thinks the size is 100x100, when really is 150x150.
Looks like its reducing the image by the density.
Can anybody explain this and how to avoid this.
Thanks
I am working on a similar issue, try this:
TypedValue typedValue = new TypedValue();
//density none divides by the density, density default keeps the original size
typedValue.density = TypedValue.DENSITY_DEFAULT;
Drawable d = Drawable.createFromResourceStream(null, typedValue, fis, "icon");
I am still working through how to develop a general solution to pick resolution/resize images from a generic stream instead of the drawable-* directories.
Rescale the image to desired dimension:
d = Drawable.createFromPath(filePath);
if (d != null) {
Bitmap bitmapOrg = ((BitmapDrawable) d).getBitmap();
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
int newWidth = 170;
int newHeight = 170;
// calculate the scale
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
d = new BitmapDrawable(resizedBitmap);
}
Try BitmapDrawable#setTargetDensity:
Bitmap b = BitmapFactory.decodeFile(path)
BitmapDrawable bmd = new BitmapDrawable(b);
bmd.setTargetDensity(getResources().getDisplayMetrics());
Set some dimensions in device independent pixels (or DIPs).

Categories

Resources