Everyone who tries to use gradients in the images on mobile device comes to the problem: how to make gradients look nicely? The answer is simple – dithering.

I will try to give some tips here about dithering images for Android devices. This is updated version of my previous post about dithering.

First of all you can make dithering in 2 ways:

  1. Dither images from the code or XML on the fly
  2. Pre-dither images in image editor software

Dither images from code

Let’s consider an example: you are trying to make a perfect button for your perfect UI.
You made a superb sketch in (let’s say photoshop) and want to transfer it to your G1 device. In the image editor software the button looks nice:

original button in photoshop

Then try to insert it to the Android Activity layout as ImageView with android:src.

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/b1" />

android - no dither

It looks… horrible isn’t it? Let’s try to apply dithering from XML.

Create new drawable:

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

and use it for the ImageView above. The result:

Android dither with xml
the same.
Because dithering in Android is applying only for stretchable or tile images. Why? I don’t know. If you know – please write me. I will take a look at the platform code later).

Then let’s add tile mode:

<?xml version="1.0" encoding="UTF-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/b1"
    android:tileMode="repeat"
    android:dither="true" />

And magic comes to your Android device:

Android tile and dither

You can also get the same result if you make a nine-patch image like this one:

nine-patch android dither

apply dither from XML and set drawable as ImageView background

<?xml version="1.0" encoding="UTF-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/btn_red"
    android:dither="true" />

or you can even do the same from the java code:

findViewById(R.id.ImageView01).getBackground().setDither(true);

Dithering images in dialogs

If you will try to do the same things in Dialog activities with transparent background – you would probably fail. Because when you have transparent dialog background the platform doesn’t know about underlying layer when rendering your image.

But here is another solution! You can set the flag in the Dialog window manager.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_DITHER, WindowManager.LayoutParams.FLAG_DITHER);

That works like a charm ;)

Pre-dither images

Of course sometimes you have to pre-dither your images. For example you a painting non-stretchable image on canvas in onDraw method and cannot dither it on the fly. Or you want to do this for performance reason.

You can simply apply 1% noise in photoshop:

pre-dither - apply noise in photoshop

you will get something like this:

pre-dither - apply noise in photoshop

Or you can use special plug-ins like 5-6-5 (http://www.telegraphics.com.au/sw/)

5-6-5

5-6-5 dithering

Plug-in is better that just a noise because you get PNG image with reasonable size.

Original image: 1218 bytes
1% noise: 14960 bytes
5-6-5 plug-in: 2026 bytes

And render on device.

different android dither

different android dither

1 – without dither
2 – program dither
3 – dither with noise
4 – 5-6-5 plug-in dither

Happy dithering!