Resource to bitmap conversion results in poor quality - android

I never really noticed it before but when I change the image of an imageview using setImageBitmap, using a bitmap which is decoded from resources using BitmapFactory, then the quality of image deteriorates and I don't know why.
I even played around with BitmapFactoryOptions like options.inPreferredConfig, options.inJustDecodeBounds, options.inDither, but the results were pretty much the same; a poor quality image.
On the other if I just use setImageResource, the image doesn't deteriorates and is in best quality possible.
So basically these two codes
Bitmap b=BitmapFactory.decodeResource(getResources(), R.drawable.keypad,options); iv.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.keypad))
iv.setImageResource(R.drawable.messages);
results in different image quality.
Can anybody explain why? And how to solve this quality issue using code 1.

If you have blurry images using the BitmapFactory.decodeResource method, you can use this code:
Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap b = BitmapFactory.decodeResource(getResources(), path, options);
iv.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.keypad));
Setting the inScaled parameter of BitmapFactory.Options class to false, will prevent blurry images on low screen resolutions since it will prevent scalling as mentioned in the answer of this previous SO question. Maybe you have already tried this but i thought worth mentioning.

Related

getDrawingCache distorted quality of bitmap

I am trying to take screenshot of a view using getDrawingCache() method. When it gives bitmap that bitmap have not the same quality which i can see on the application. Below is the code which i am using :
view.buildDrawingCache();
Bitmap cacheBitmap = view.getDrawingCache();
ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
cacheBitmap.compress(Bitmap.CompressFormat.PNG, 100, streamOut);
byte[] bitmapDataArry = streamOut.toByteArray();
I already tried few stuff which i got from google and SO. Like this improve quality of getdrawingcache and improve quality of image. But still not getting the pure image quality. Can anyone have any suggestion about this or any else method for taking screenshot without loosing quality.
I guess your problem is that you taka a screenshot on a small screen device and there the drawing cache is smaller and therefore the screenshot itself is smaller but looks ok because of the phone screen which is also small. If you then upload this image that you've got from getDrawingCache to your server and then try to show it on another device with higher resolution screen the quality will be grainy and pixelated. If you are in this case then showing the original image or cropped version of it will help you maintain quality.
There is another case when your view might be getting the old cache.
Here you can destroyDrawingCache() and then buildDrawingCache().

Faster image processing

Can someone suggest me a library that can do simplest operations like scale, crop, rotate without loading image fully into memory?
The situation: I need to scale image down from a very large size, but the scaled down image is still too large to be allocated in memory (if we use standard android tools). Since I only need to upload scaled down version, I thought of scaling it through native library and upload it through FileInputStream.
I've tried to use ImageMagic and it does the job, but performance is very poor (maybe there is a way to speed things up?)
Might want to check out OpenCV for Android
You can use the original Android Bitmap functionality by pulling the image into memory but allowing Android to sample the image before it is loaded.
For example:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap myBitmap = BitmapFactory.decodeStream(inputstream,null,options);
This will load your bitmap into memory with half the memory footprint of the full image. You can experiment with changing the inSampleSize to get a good fit for your application.
You can also calculate the sample size on the fly, if you know the final image size you are aiming for, you can get the current file size of the image before you load it into memory and calculate the sample size using the equation inSampleSize = OriginalSize/RequiredSize. Though sample size is best used when it is a power of 2, so you can make adjustments for this.
Edit:
A great example here https://stackoverflow.com/a/823966/637545

Android - Bitmap quality loss?

I use transparent png image for my app, but when app runs the image loses its quality and it is not exactly same, its kind of distorted also blurred. Is there something that i can do, like bitmap options?
mBitmap = BitmapFactory.decodeResource(res,R.drawable.img1);
I had this problem too. I did solve it using another format than png (in my case jpg was enough). If you still want to use an alpha channel your only remaining choice is gif, even if this wouldn't be the best choice normally.
Could it be the screen pixel density does not match that of your Bitmap? Unless you specify otherwise, your Bitmap is assumed to be at 160dpi, so it will be rescaled as necessary, depending on the device, when you load it.
You can have different versions of your Bitmap, designed for different pixel densities. Just like app icons, these go into the appropriate res/drawable-*dpi/ subdirectories.
I had the same issue when trying to process pictures from android camera.
I solved using this code:
Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDensity = 96;
Bitmap originalPicture = BitmapFactory.decodeFile(pictureFile.getPath(), options );
It seems this problem is related to the RGB format of your image and the dither option.

Large source ImageView animation

What's the best image file format for Android in terms of memory? PNG is recommended for iOS as xCode does some magic with it.. Is it the same for Android?
I'm currently developing a big app with multiple animations going on (sliding in screens, fading etc etc). All works well so far! However I have noticed the view animation where the view contains an ImageView with a (quite large) PNG as the source is a bit laggy.
Obviously I can make the PNG smaller, but is there anything extra I can do to reduce the amount of memory the ImageView takes up/makes the animation smooth? I know PNG has a much larger file size than JPEG, but I can't see this being a problem, the JPEG or PNG (I assume) is eventually stored as an array of colours, so they would both take up the same memory. PNG is probably better for loading due to less cycles uncompressing. Again I only assume, my knowledge of image file formats is null.
Alternatively is there anything else causing the lag? Is the bitmap scaled to fit the view each onDraw() during the animation so should I scale the bitmap in code before giving it to the ImageView?
Thanks,
The formats supported by Android are: PNG, JPG and GIF (also 9.png).
The recomendated is PNG as said in dev guide
All of them are stored in memory as a Bitmap, so the most important thing is the color deph, like this:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon, options);
More info: stackoverflow
and add (after honeycomb):
<application
android:largeHeap="true"
...
to your manifest file :=)
thanks to my dear friend :)

Android, Canvas and Screens

I think I've got quiet a common problem in regards to Android development, but cant seem to find the answer I'm looking for.
If I make a canvas on Photoshop 800x480px (240ppi) and make a logo within that canvas that is 282 x 121px, I cant understand why when I display the image it takes up 3/4 of the screen in my emulator with the same 800x480px.
The code I use to display the logo is the following
Bitmap logo = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
//in the onDraw
canvas.drawBitmap(logo, 0, 0, null);
Thanks in advance!
Possible Solution
Not sure if this is the best way to do things and would appriciate any feedback, I came across this solution (typically when you've already posted a question :D ) was to code the image as follows:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
//Load images
logo = BitmapFactory.decodeResource(getResources(), R.drawable.logo, options);
The image was probably only taking up 3/4 of the screen in the emulator because of the pre-scaling android sometimes does.
Check out this article on how to handle multiple resolutions and screen sizes.
You could try placing the drawable into a 'res/drawable-mdpi/' directory or a 'res/drawable-ldpi/' to differentiate between medium density and low density screens. Another option is to place it in a 'res/drawable-nodpi/' directory to prevent any pre-scaling. I've even placed some images in the 'res/raw' folder to get the same effect.
However, if your current method works, go for it!

Categories

Resources