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.
Related
For a splashscreen I use an image which contains a white background (pure white - checked in Photoshop). For some reason it shows a slight green bg vs. the activity's default white bg - as marked in the screenshot. Only in some devices, like the
I add this as single view in a frame layout to the activity:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
android:src="#drawable/splashscreen" />
</FrameLayout>
Any idea? I read about RGB888 vs. RGB565 issues, but couldn't find a proper solution.
Note: I sure could make change the white in the image to transparent, but would prefer to understand the problem and find a proper solution.
This is really annoying. I wonder, why so few people encountered this problem as it should appear on all 32-bit displays.
You mentioned right about RGB888 format. The cause of the problem is that regardless of the original bitmap format in the APK files all bitmaps are compressed (in my case into indexed 256-color! wtf?).
I couldn't find the way to prevent it, so if anyone knows the proper solution, please tell.
However, I found two solutions for the white color problem.
1) Per-bitmap: Say, we have a drawable bitmap resource called #drawable/mypng, which causes the problem. We need to add an additional XML drawable drawable/mypng_nofilter.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/mypng"
android:filter="false"
/>
and use #drawable/mypng_nofilter instead.
2) For entire activity: In activity onCreate method we need to add
getWindow().setFormat(PixelFormat.RGB_565);
Now the window has 16-bit color depth and all bitmaps appear "properly" white.
Again, I would prefer to have 32-bit color depth, but I don't know how to control compile-time image compression.
I have solved this issue by changing the Bitmap.CompressFormat type to PNG instead of JPEG:
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.nouv);
Bitmap bitmap = (Bitmap)((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
I encountered the same problem with network loaded images. I solved the issue by disabling bitmap filter. Since I do not have the issue on ICS and newer devices, I turned off the bitmap filter only for pre-ICS devices. Following is the code I used (setting network loaded bitmap to the ImageView.)
BitmapDrawable bitmapDrawable = new BitmapDrawable(imageView.getContext().getResources(), bitmap);
bitmapDrawable.setFilterBitmap(false);
imageView.setImageDrawable(bitmapDrawable);
After using all the solutions in the Stackoverflow.
From changing android:src to app:srcCompact and many other solutions.
The thing which helped me was my image was inside drawable-anydpi and I moved the image from drawable-anydpi to drawable and it worked for me after 2 hours of research.
P.S: It might help someone too that's why I put it over here. :)
As your image only have a picture in its middle, I would advise you to set:
android:scaleType="centerCrop"
It will crop some part of your picture, at left and right, but will use the whole screen...
You can also define a background to your FrameLayout or your ImageView using the color of your picture (which seems to be F8FCF8):
android:background="#F8FCF8"
On emulators running Android 4.0 or 4.0.3, I am seeing horrible colour banding which I can't seem to get rid of. On every other Android version I have tested, gradients look smooth.
I have a SurfaceView which is configured as RGBX_8888, and the banding is not present in the rendered canvas. If I manually dither the image by overlaying a noise pattern at the end of rendering I can make the gradients smooth again, though obviously at a cost to performance which I'd rather avoid.
So the banding is being introduced later. I can only assume that, on 4.0+, my SurfaceView is being quantized to a lower bit-depth at some point between it being drawn and being displayed, and I can see from a screen capture that gradients are stepping 8 values at a time in each channel, suggesting a quantization to 555 (not 565).
I added the following to my Activity onCreate function, but it made no difference.
getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);
I also tried putting the above in onAttachedToWindow() instead, but there was still no change.
(I believe that RGBA_8888 is the default window format anyway for 2.2 and above, so it's little surprise that explicitly setting that format has no effect on 4.0+.)
Which leaves the question, if the source is 8888 and the destination is 8888, what is introducing the quantization/banding and why does it only appear on 4.0+?
Very puzzling. I wonder if anyone can shed some light?
Try dis..
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap gradient = BitmapFactory.decodeResource(getResources(), R.drawable.gradient, options);
findViewById(R.id.main).setBackgroundDrawable(new BitmapDrawable(gradient));
Turning on the emulator "Use Host GPU" option fixed the color problems for me, credit goes to this answer https://stackoverflow.com/a/17166234/1287459
In my case I was using Android 4.2.2.
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 :)
My Android application loads images, does some processing and saves the processed images on the SD card. I save temporary files to the SD card instead of using buffers. For example, reading a background, scrolling the image, drawing an annotation, merging background and annotation in a saved temp file to use as next background, and so forth. Typical snippets:
bitmap = Bitmap.createBitmap(imageSizeX, imageSizeY, Bitmap.Config.ARGB_8888);
bitmap = BitmapFactory.decodeFile(path, options);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
Everything works fine but in some cases the saved images have added noise similar to that described in this post:
Bitmap resizing and rotating: linear noise
The author of the post cited solved the problem by subsampling, but I don't wish to do that.
I have tried the solutions suggested here:
http://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/#more-1218
which if I understand correctly should be achieved by setting:
getWindow().setFormat(PixelFormat.TRANSLUCENT);
to force 32 bit.
which does not change much. Setting or not setting the dither flag does not seem to change much either. Any other ideas?
In answer to my own question:
The noise disappears, or at least the result is way better, by compressing to .png instead of .jpg
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
The same sky which looks like a carpet texture in .jpg looks smooth and clean in .png. Since the difference is much more evident than the usual difference between the same image compressed to .png and .jpg, I guess it depends on the Android implementation. Setting explicitly TRANSLUCENT and DITHER does not make much difference one way or another.
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 .