« Smerity.com

Dithering: how it works and why it matters

When most programmers and designers think about dithering, they think of images and animations from an ancient era or an annoying animated GIF. Surprisingly though dithering is still alive and well in many, many places. Some of those places would give web designers nightmares.

Brief Reminder: Colours in the Browser (Roses are #F00...)

In the browser, as defined by the W3 spec for CSS3 colours, you'll usually see colours represented in a few different ways:

  • #rgb - three-digit RGB notation
  • #rrggbb - six-digit RGB notation
  • rgb(rrr, ggg, bbb) - integer valued (0-255) RGB notation
  • rgb(r%, g%, b%) - percentage valued RGB notation
  • rgba(rrr, ggg, bbb, aaa) - integer valued (0-255) RGB notation with an alpha channel
  • rgba(r%, g%, b%, a%) - percentage valued RGB notation with an alpha channel

Tangent: the three-digit RGB notation is expanded to the six-bit by repeating the hex digit (#rgb becomes #rrggbb instead of #r0g0b0). This, amongst other things, ensures that black (#000) and white (#FFF) expand to absolute black and white (#000000 and #FFFFFF respectively).

All the above are just ways of telling the browser how much red, green and blue go into making a given colour. For a standard browser, this is conveyed using 24 bits (8 bits per each of the three colour channels). This means you can view a total of over 16 million colours with the standard 24 bit colour display. Sounds pretty reasonable, right?

Limited Colours & Dithering

Imagine you've been thrown back in time, to the days when computers were slow and bits were expensive. How can you improve the perceived image quality if you're limited to only displaying a palette of N different colours on the screen at once? You cheat. Dithering takes advantage of the human eye's tendency to "mix" two colors in close proximity to one another.

Spatial Dithering

If you intermix two different colours evenly and discretely enough, the human eye sees an average of the two colours. In this case, when red and blue are mixed in a checkerboard pattern, the result appears a convincing purple. This is the traditonal case of dithering and is most commonly seen in old school games and animated GIFs due to their lack of a full colour palette.

Temporal Dithering

You can also alternate quickly between two colours to end up with what appears to be the average of the two. This is referred to as temporal dithering. You'll most commonly find temporal dithering in hardware, specifically to improve the appearance of an image on a sub-par television or monitor display.

I've made an example of dithering using frame rate control but I preface it with the warning that it may be unsafe for those with epilepsy. If you're still happy that it won't impact you medically and you don't mind your CPU bursting into flames, click here. Why not use an animated GIF, you might ask? It turns out that browsers don't like rapidly changing GIFs all that much. The requestAnimationFrame is the best way to deal with rapidly changing elements in a browser. Better yet would be to actually implement it in something natively, but you wouldn't download arbitrary code off a website and run it, right..? ;)

But everyone has good monitors now, right? No need for dithering!

Minor issue: colour banding in gradients

If you were creating a soft linear gradient on a website, you might hit an issue. Imagine a soft shifting gradient from dark grey (#333) to lighter grey (#666) on a website.

Major issue: low quality 18-bit monitors

That red might not be the red you expected...

Interesting Links