My application load images from server via HTTP and save it into files. Then I use this code to get Drawable and view it:
File f=new File(path);
if(f.exists()) {
Bitmap bmp = BitmapFactory.decodeFile(f.getAbsolutePath());
if(bmp!=null) {
DisplayMetrics dm = m_activity.getResources().getDisplayMetrics();
bmp.setDensity(dm.densityDpi);
Drawable drawable=new BitmapDrawable(context.getResources(), bmp);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
return drawable;
}
}
It working fine on Samsung Galaxy S2. But on Samsung Galaxy S4 this images too small. For example:
On S2:
On S4:
I need to display it equally on all devices with various display's resolution. Is it possible? How to implement this?
I think I can help you. I had this same kind of problem myself. What you need to do is find how much larger this new screen is than your old one, by first getting the dimensions of your device and putting them in for widthOfStandardDevice and heightOfStandardDevice.Once you know how much larger the new screen is then your old one, you would make two multipliers to multiply everything by. You can now say set the size of the bitmap to bitmap_width and bitmap_height.
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
float widthMultiplier = width/widthOfStandardDevice;
float heightMultiplier = height/heightOfStandardDevice;
int bitmap_width = (int)(600 * widthMultiplier);
int bitmap_height = (int)(800 * heightMultiplier);
The basic problem is that devices with a HIGHER resolution will make the images appear SMALLER. You need to scale the "intrinsic" size proportionately to your device resolution.
One good solution (as Sheldon suggested) is to use a Scaled Bitmap:
How to scale bitmap to screen size?
Android image on tablets and phones
you don't have to scale the bitmap, since scaling it up will mean it will use more memory.
instead, you can just tell the imageView how large you wish it to be , and let it show the bitmap in the exact size you wish it to be (use dp).
if you do wish to set the bitmap size yourself, check out this link if image quality is important or this link if speed is more important
Related
I have images of size 1080P , now i do not want to use different variations of images that we put in RES folder . I am going to install this app on 1K devices with random images , so thats not feasible to have different versions of images.
Can we scale it on runtime , still getting the best quality ?
To scale images use following
Bitmap bitmap = BitmapFactory.decodeResource(
getResources(), R.drawable.app_bg);
scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
then assign this scaledBitmap to any ImageView or any other View. This will scale the original Bitmap to the requested width and height. To get width and height of the device screen use following
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
EDIT
In order to handle MemoryLeakException add scaledBitmap.recycle() after using this Bitmap.
When I create a Canvas from a bitmap that is generated with the BitmapFactory.decodeResources from a drawable resource that is a png image file of 400 x 400 pixels, the Canvas height and width are not 400 but 600!
In the code below, the drawable resource wind_scale is a png file that I generated with PHP as a 400 x 400 image.
Bitmap workingBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.wind_scale, options);
Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas mCanvas = new Canvas(mutableBitmap);
int mHeight = mCanvas.getHeight(); int mWidth = mCanvas.getWidth(); both 600!!!!
Is this behavior expected? If so, why is there a 50% increase?
I am not 100% sure of the problem here but it's similar to another SO question (Getting weird font size after setting it programmatically). The problem there was also a 50% difference in values, and it was due to a comparison of sp units to pixels on the OP's device with a screen density ratio of 1.5.
You might check into BitmapFactory.Options; there are several scale and density flags that may help. My best guess is that the image is being scaled for the device and this is causing a measurement mismatch.
Canvas it's not related to the bitmap size but to the device available screen size. If you try that code on different devices (or virtual devices) you will find different results.
Canvas and Drawables
It seems that setting a wallpaper on Android just doesn't work in any useful way.
If you get an image from your phone and set it as the wallpaper, it's way too big for the screen
If you resize it (either using a createBitmap() function that allows you to specify size, or the ridiculously useless createScaledBitmap()) it goes all jaggy and out of focus
If you use some freaky hacks to fix the quality of the image, it's better, but still not perfectly clear by any stretch.
If you attempt to get the current wallpaper and set that, it still seems to make it too big. It appears to give you the original image file, forcing you to resize it, which doesn't work.
Now, the phone's internal software is perfectly capable of resizing an image to be smaller with no reduction of quality. Why does it not share this functionality?
WallpaperManager wallpaperManager = WallpaperManager.getInstance(Spinnerz.this);
// gets the image from file, inexplicably upside down.
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "DCIM/Camera/Zedz.jpg");
// use some rotation to get it on an angle that matches the screen.
Matrix bitmapTransforms = new Matrix();
bitmapTransforms.setRotate(90); // flip back upright
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),bitmapTransforms, false); // create bitmap from bitmap from file, using the rotate matrix
// lets set it exactly to the resolution of my Samsung Galaxy S2: 480x800 pixels.
// This function appears to exist specifically to scale a bitmap object - should do a good job of it!
bitmap = Bitmap.createScaledBitmap(bitmap, 480, 800, false);
wallpaperManager.setBitmap(bitmap);
// result is quite a jaggy image - not suitable as a wallpaper.
PIC:
Try this ,
Display d = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
So I need to resize my sprites with respect to the phones screen size,
I do the following:
final Display display = getWindowManager().getDefaultDisplay();
cameraWidth = display.getWidth();
cameraHeight = display.getHeight();
//check to load male or female
Intent sender=getIntent();
String extraData=sender.getExtras().getString("char");
if(extraData.contains("1"))
{
isMale = 1;
}
else
{
isMale = 0;
}
mCamera = new Camera(0, 0, cameraWidth, cameraHeight);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(cameraWidth, cameraHeight), mCamera)
.setNeedsMusic(true).setNeedsSound(true));
However, for sprites, ie the player and enemies, I give them an arbitrary size such as 50 pix by 50pix - Now on small screens they appear really large! how can I resize them with respect to the screen size?
Also, These images are loaded from assets folder, so they have nothing to do with HDPI and LHPI image folders.
Thanks in advance community.
You should either use SVG graphics that are scalable on different device screens.
What i would suggest is you set the CAMERA_WIDTH and HEIGHT to a screen size no matter what size device it is on.
For example, for a project i am making i have a camera width and height of 800x480.
This way you dont have to worry about resizing any sprites. They all appear the same on each device while scaling up by the engine with the RationResolutionPolicy.
This is the best way to go about this.
If you set the screens size based on the device you will have to supple different graphics for each.
So i would recommend using SVG graphics so that when the images are scaled up automatically by the engine they dont loose quality. OR you can use png's and make them large, that way they will only be scaled down. And as you know they wont lose image quality by scaling down.
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!
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
Use decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts) and in opts set inDesity to let say 160.
Worked for me, see this. But I have to say, I think SQLite is doing it right, and the android drawable is incorrectly sized.