Android Color formats (RGB565, ARGB8888)

Zippy picture Zippy · Mar 2, 2013 · Viewed 29.2k times · Source
    getHolder().setFormat(PixelFormat.RGBA_888);        

    Options options = new BitmapFactory.Options();       
    options.inDither=true;                               
    options.inScaled = true; 
    options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
    options.inPurgeable=true;

(Bitmat created using options above)

When using the above code, I get the following results.........

  • No colour banding on my Tablet device
  • Noticeable colour banding on test mobile (Samsung Galaxy Ace)

    getHolder().setFormat(PixelFormat.RGBA_888);        
    
    Options options = new BitmapFactory.Options();       
    options.inDither=true;                               
    options.inScaled = true; 
    options.inPreferredConfig = Bitmap.Config.ARGB_565; 
    options.inPurgeable=true;
    
  • No colour banding on my tablet

  • Noticible colour banding on the Galaxy Ace
  • Same results as above

    getHolder().setFormat(PixelFormat.RGB_565);     
    
    Options options = new BitmapFactory.Options();       
    options.inDither=true;                               
    options.inScaled = true; 
    options.inPreferredConfig = Bitmap.Config.RGB_565; 
    options.inPurgeable=true;
    
  • Colour banding on my tablet

  • colour banding on the SG Ace

    getHolder().setFormat(PixelFormat.RGB_565);     
    
    Options options = new BitmapFactory.Options();       
    options.inDither=true;                               
    options.inScaled = true; 
    options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
    options.inPurgeable=true;
    
  • Colour banding on my tablet

  • colour banding on the SG Ace

So, in conclusion, only the PixelFormat.xxxx part seems to make any difference. My understanding is that this is to set the holder colour format. This will affect everything drawn. (ie, everything will take that format).

Could someone explain what the purpose of the following line is please?

options.inPreferredConfig = Bitmap.Config.xxxxxxx

This doesn't seem to have any effect on the bitmap that has been drawn.

Performance is paramount, so I may have to change my original png files so they don't have gradients, (ie, to draw them as RGB565 - is this advisable or should I stick with 8888?) or should dithering sort that out? (because as you can see, I have it enabled but it doesn't seem to help).

Any ideas why the banding is always there on the Ace? Could it be a hardware limitation?

Thanks all this is very confusing.

(PS I have read the official guide, I always look at that before posting a question to SO as well as looking at other related SO questions, but the official guide (as is too often the case), doesn't clear this up for me and I couldn't find the answers through other questions, so apologies if it is here already).

Answer

Srdjan Grubor picture Srdjan Grubor · Mar 2, 2013

565 format is default since it can be drawn quicker and requires less processing power. As for your SG Ace, I believe that a while back only certain versions of Android supported the 8888 color.

To get one of my app backgrounds to not band, I had to do the following:

1 - Add background to drawable folder

2 - Create background_dithered.xml with the following content:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:src="@drawable/background" />

3 - in Activity code:

@Override
public void onAttachedToWindow() {
        super.onAttachedToWindow();

        getWindow().setFormat(PixelFormat.RGBA_8888);
}