Android Color formats (RGB565, ARGB8888)

30,147

Solution 1

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);
}       

Solution 2

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.

Different Bitmap configurations will have different memory footprints. RGB_565 is a 16 bit colour format. ARGB_8888 is a 32 bit format.

Regardless of which getHolder().setFormat(); configuration you've chosen, or how it's being drawn, an ARGB_8888 Bitmap is going to be significantly larger (in memory) than a Bitmap in RGB_565 format.

Share:
30,147
Zippy
Author by

Zippy

Oracle Certified Associate, Java and Android developer. All-round lover of all things tech like my cutting edge ZX-81!

Updated on July 09, 2022

Comments

  • Zippy
    Zippy almost 2 years
        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).

  • Zippy
    Zippy over 11 years
    Ah, that might explain the problem with the Ace, will your implementation above work with a surfaceview? (I'm drawing the background with Canvas.drawbitmap) - thank you
  • Zippy
    Zippy over 11 years
    Thank @TylerM, I understand about the different formats and memory size etc, what I don't understand is the purpose of the line You/I quoted above. Are you saying that if I have an RGB8888 image and load it with inPreferredConfig set to RGB565 it will be smaller in memory? If this is the case why does it stil display with no bandin (ie, in a 32bit format) when I have the holder set to 8888? Sorry, if this doesn't make sense but I don't understand....... thanks :-/
  • Srdjan Grubor
    Srdjan Grubor over 11 years
    I'm not sure as I only did this with a static png but you could try doing the set format on onAttachedToWindow override
  • androidguy
    androidguy almost 7 years
    Pretty sure ARGB_8888 is the default now.