Why do we need dithering?

1 day ago 2

Before we all mute the word 'dithering' I thought I'd explain a little bit about why we needed to dither digital images in the first place. Although it's an aesthetic now, we used to need dithering to trick our eyes into seeing more colors than were actually there. 👇

So in the early days of computing, memory was scarce and we couldn't store a lot of color detail. To get around this we used limited palettes with lookup tables or really low bit depth colors, to reduce the number of colors in an image, also called quantization.

The problem with quantization is it creates hard steps where there should be gradual gradients - we don't have a color in between these. This is where dithering comes in. We can approximate this gradient by adding some noise with the two neighbouring colors.

Dithering is effective because of something called spatial averaging - basically your eye takes an average of a small area of color. Dithering tricks our eyes into inferring a smooth step between the two banks of color, like a low pass filter.

So how do we dither an image? Well there are quite a few approaches so lets start with the simple one, ordered dithering. For the sake of simplicity lets use a monochrome image. Our goal is to recreate the grey tones in the image using just black and white.

To start, we create a 2x2 Bayer matrix, where the values are the order in which we will process the pixels. We then scale those values to the range we need, 0-255, which gives us a threshold map we can use to compare pixels against.

Next, we divide the image into 2x2 pixel groups and compare each pixel value to the values in our map, in that weird criss-cross order. If it's higher than the value in our map, we turn it white and if it's lower we turn it black.

Because we have a 2x2 matrix, there's actually only 5 possible results for any quadrant, which means there are only 3 shades of grey in between white and black. Increasing the size of the threshold map increases the effective shades of grey and therefore the detail level.

The problem with ordered dithering is that our threshold map produces patterns that are pretty noticeable. A better approach is something called error diffusion dithering, specifically the Floyd–Steinberg algorithm.

Instead of using a map, we set a single threshold value like 128. We evaluate each pixel against this threshold like before. This time, we take the difference between the original value and our new value and apply that difference, known as the error, to surrounding pixels.

The idea being that if one pixel is much brighter than the original, neighbouring pixels are made darker to compensate. We diffuse the error by adding it to neighbouring pixels according to this matrix of weights. The error is signed, meaning it can be positive or negative.

There are actually tons of other dithering algorithms but these are the two most common ones. We don't really need dithering anymore because we have high bit-depth colors so its largely just a retro aesthetic now.

Anyway, that's dithering. I put this together because I've been writing about dithering, as well as other effects like Guassian blurs, edge detection, noise etc for makingsoftware.com If that's the sort of thing you're into, sign up to the mailing list.

Read Entire Article