I created a background .png for my application in GIMP. It's resolution is 640x480, which from googling, seems to be the resolution for a default emulator. My problem is when I apply the background to the RelativeLayout with android:background=#drawable/bg and run it, there are lots of artifacts in the image. As if the emulator could not provide enough colors to display the .png correctly. What is going on here?
P.S. This image is nothing to fancy, just simple lines and radial gradients.
It's resolution is 640x480, which from
googling, seems to be the resolution
for a default emulator
640x480 is not even an officially-supported resolution in Android, let alone a "default" one. Here is the list of supported resolutions.
Also, you want to watch your color depth. I forget the details, but not everything can necessarily handle 24-bit color, due to LCD limitations.
i've gathered 3 possible solutions:
for each problematic image that you have, create and use a bitmap drawable in the xml.
the disadvantage is that you create multiple files. i've tested the other special flags (including the code changes), and haven't noticed any difference.
res/drawable/image_file.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/problematic_image" />
put the problematic image in the drawable-nodpi folder. the disadvantage is that it will use more RAM this way, as it doesn't downscale according to the density. a similar approach can be done in code:
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = 1;
options.inSampleSize = 1;
options.inTargetDensity = 1;
options.inJustDecodeBounds = false;
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.problematic_image, options);
imageView.setImageBitmap(bitmap);
if the file is a png file, take a pixel that is least noticable (for example the bottom-left), and change its opacity to 254 instead of 255.
the disadvantage of this method is that it makes the image to take more space , and change the image itself.
all methods worked on galaxy s and galaxy s2 , with android 2.3.x .
Related
Im having an issue with my backgrounds. I get horrible image banding when setting background images with gradients. When I set the background in my root layout I do it as follows:
android:background="#drawable/GradientImage"
I have also tried setting the background of my root layout in the code (after removing background from axml):
Window.SetFormat(Android.Graphics.Format.Rgbx8888);
Window.AddFlags(Android.Views.WindowManagerFlags.Dither);
BitmapFactory.Options options = new BitmapFactory.Options();
options.InPreferredConfig = Bitmap.Config.Argb8888;
Bitmap gradient = BitmapFactory.DecodeResource(Resources, Resource.Drawable.Background_640,options);
sv.SetBackgroundDrawable(new BitmapDrawable(gradient));
This is done in OnCreate and unfortunately does not fix the issue,
Has anyone ever came across this issue? Does anyone now how to fix this.
This code works for me (in onCreate())
getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);
Also, when using PNG images, make sure they are using 32-bit color depth,
because some image editing programs save them as 24-bit by default.
For example, in GIMP, you can force the PNG image to be saved as 32-bit
by adding alpha channel.
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.
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 :)
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!
I have some .png files in my app. I need to load these during runtime, and get the exact colors of certain pixels from them. It's important, that I do not want to scale these pictures. I don't show them on the UI directly, they serve as maps.
Now, on Android 1.5, there's no problem with this. I put these images in the '/res/drawable' dir, load them with BitmapFactory into a Bitmap object, and use it to get the color of the desired pixels. E.g. pixel (100, 50) has the color RGB(100, 1, 100).
On Android 2.2 tho, the same procedure results varying colors (for the same pixel), so I get RGB(99, 3, 102) / RGB(101, 2, 99) / etc. for the same (100, 50) pixel. I checked the resolution of the Bitmap object, it seems that is didn't get scaled.
Could somebody explain, why I get distorted colour values?
Solved: It appears, that on Android 2.2, I have to set the correct bitmap configuration. Somehow, versions below 2.2 managed to do this (or maybe fewer configs are supported on those, and the system guessed the config correctly, don't know).
Anyways, here's the code I use now:
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither=false;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap mask = BitmapFactory.decodeResource(getResources(), R.drawable.picture, opt);
Go make yourself a bitmap thats entirely the same color of the pixel in question. Make the size of this bitmap the same resolution of the one your currrently using. Load it up and check the RGB values of the same pixel (or any pixel) you are having problems with.
This should tell you whether your problem is either scaling, which is what I think it is, or possibly a problem in the color translation.
If you don't find an answer quickly, my pragmatist streak would ask how hard it is to parse the .png yourself, to get completely deterministic results independent of any changes in the platform.
My 2.3 devices (Nexus One and S) worked fine without setting "opt.inPreferredConfig", but it appears that 2.2 requires it for accurate RGBs.