Image Dithering, Explained

After reading this you can predict what Floyd-Steinberg, Atkinson and ordered Bayer dithering will do to a photo, choose the right palette for a retro look, and avoid the banding and dirt that ruin cheap conversions.

Dithering is the trick that lets a small palette look like a large one. Take a smooth gray gradient and reduce it to pure black and white. Without dithering you get flat bands with hard steps between them. With dithering you get a spray of black and white dots whose local density tracks the original brightness, so from a normal viewing distance your eye blends them back into gray.

The classic hook is a 1-bit portrait. A face has thousands of tonal values. A 1-bit image has two. A good error-diffusion dither turns that face into a Newspaper-style stipple that still reads as a face, while a naive threshold turns it into a blotchy mask. Same two colors, completely different result. The difference is entirely in how the rounding error gets handled.

What dithering actually does

Every pixel in your source has a color that usually is not in your target palette. Quantization means picking the nearest palette color. That introduces an error: the difference between what the pixel wanted and what it got. Threshold dithering throws that error away. Error diffusion keeps it and spreads it to neighboring pixels that have not been processed yet. Ordered dithering does not track error at all; instead it nudges each pixel up or down by a fixed amount read from a small repeating matrix.

Palette
The fixed set of colors the output may use. 1-bit is two colors. The classic Game Boy palette is four shades of green.
Quantization
Replacing a pixel's color with the nearest available palette color.
Quantization error
Old value minus new value, per channel. This is what error diffusion redistributes.
Diffusion kernel
The pattern of weights that decides how much error each neighbor receives.

When to use it, and when not

Reach for dithering when your palette is small and your image has smooth gradients. Skies, skin, soft shadows and lighting falloff all band badly under plain quantization, and dithering hides the bands. It is also the honest way to get an authentic retro look: real 8-bit and print output dithered because they had to, so the texture is part of the aesthetic.

Skip it when the palette is already large. A 24-bit photo saved as PNG needs no dithering. Skip it for flat vector art, logos and screenshots of text, where the source has few colors and hard edges; dithering there just adds noise and can make text fuzzy. And be careful before scaling: a dithered image does not survive resampling well, because the dot pattern is tuned to one exact pixel grid.

Dithering fights compression. The random-looking dot texture has high spatial frequency, which is exactly what PNG's filters and JPEG's DCT struggle to compress. A dithered 1-bit PNG can be larger than the same image left as smooth grayscale. Test file size before you assume dithering makes files smaller.

The Floyd-Steinberg formula

Floyd-Steinberg is the most common error-diffusion dither. It processes pixels left to right, top to bottom. For each pixel it finds the nearest palette color, computes the error, then pushes fractions of that error to four not-yet-processed neighbors.

e = v_{\text{old}} - v_{\text{new}}

Here v_{\text{old}} is the pixel's value before quantization and v_{\text{new}} is the nearest palette value. The error e is then spread with these weights:

\text{right} = \tfrac{7}{16}e,\quad \text{below-left} = \tfrac{3}{16}e,\quad \text{below} = \tfrac{5}{16}e,\quad \text{below-right} = \tfrac{1}{16}e

The four fractions sum to \tfrac{7}{16} + \tfrac{3}{16} + \tfrac{5}{16} + \tfrac{1}{16} = 1, so no brightness is created or destroyed overall. That conservation is why a mid-gray region ends up with roughly half its pixels white and half black. Atkinson uses a different rule: it spreads only \tfrac{6}{8} of the error over six neighbors (each getting \tfrac{1}{8}e) and discards the rest. Losing a quarter of the error gives Atkinson higher contrast and cleaner highlights, which is why it looks like a classic Macintosh screen.

A worked 1-bit example

Work through one row on a tiny grayscale image reduced to 1-bit black (0) and white (255). Values are 0 to 255. The threshold is 128: below it rounds to 0, at or above it rounds to 255.

One row of Floyd-Steinberg

Start with four pixels in a row, all the same mid value 100, with black-and-white output.

  1. Pixel 1 has value 100. Nearest of {0, 255} is 0. Error e = 100 - 0 = 100. Push \tfrac{7}{16}\times 100 = 43.75 to pixel 2.
  2. Pixel 2 now holds 100 + 43.75 = 143.75. Nearest is 255. Error e = 143.75 - 255 = -111.25. Push \tfrac{7}{16}\times(-111.25) = -48.67 to pixel 3.
  3. Pixel 3 now holds 100 - 48.67 = 51.33. Nearest is 0. Error e = 51.33. Push \tfrac{7}{16}\times 51.33 = 22.46 to pixel 4.
  4. Pixel 4 now holds 100 + 22.46 = 122.46. Nearest is 0 (just under 128). Error carries on to the next pixel.

Output for the row: black, white, black, black. Two black and one white so far, with error still travelling. Over a wide band of value 100, roughly 100/255 \approx 39\% of pixels end up white, which is the correct average brightness. That is the whole point: individual pixels are wrong, but the local average is right.

Threshold sends the whole field to black, losing all brightness. Both error-diffusion methods hold near the true 39 percent. Atkinson runs darker because it discards a quarter of the error.

Ordered dithering and the Bayer matrix

Ordered dithering does not diffuse error. It compares each pixel against a threshold that changes position by position, read from a small tiled matrix. The 4x4 Bayer matrix holds the integers 0 to 15 in a fixed scrambled order. Divide each entry by 16 to get a threshold offset, then add it to the comparison. Because the matrix repeats, you get a regular crosshatch texture rather than the organic grain of error diffusion.

The advantage is that ordered dithering is stateless and parallel: each pixel depends only on its own value and its coordinates, so the result is identical no matter what order you process in. That fixed pattern is exactly the look of 90s games and halftone print. The cost is that the crosshatch is visible and can clash with fine detail.

A smooth horizontal gradient from black to white, quantized to a chosen palette. Threshold produces hard bands; ordered Bayer produces a fixed crosshatch; Floyd-Steinberg and Atkinson produce organic grain, with Atkinson visibly darker in the midtones.

Reading the result

Judge a dither at 100 percent zoom, then step back. Three things tell you it worked. First, gradients should be smooth with no visible steps. Second, the average brightness of any region should match the source; if the whole image looks darker, you may be using Atkinson or a bad threshold. Third, the texture should sit behind the image, not on top of it: you should read the subject first and notice the dots second.

For palettes, more levels means less visible dithering. A 4-level grayscale palette only needs to fake the tones between its four fixed values, so its dot pattern is far subtler than 1-bit. The Game Boy's four greens work the same way: four levels, gentle grain.

Common mistakes

The most frequent error is dithering in the wrong color space. Pixel values in a file are usually gamma-encoded (sRGB), not linear light. If you average sRGB values directly, midtones come out too dark. For accurate brightness, convert to linear light, diffuse the error there, then convert back. Many quick tools skip this, and the result is a dither that looks muddy.

A second mistake is dithering then scaling. If you dither at 4x size and shrink, the shrink blends the dots back into gray and you lose the effect entirely. Dither last, at final output size. A third is expecting small files. As the earlier callout warns, the noise resists compression. A fourth is applying a strong dither to line art or text, where it only adds dirt.

Related tools

If you are producing retro assets, the Sprite Sheet Generator & Splitter packs dithered tiles into one sheet or slices an existing sheet apart. For text-mode output instead of dots, the ASCII Art from Image tool maps brightness to characters. When you need a quick sized stand-in rather than real art, the Placeholder Image Generator makes labeled blocks at any dimension.

Frequently asked questions

Which dither method looks best for a 1-bit photo?

Floyd-Steinberg for a smooth, organic stipple; Atkinson for higher contrast with cleaner whites, at the cost of losing about a quarter of the shadow detail. Ordered Bayer if you specifically want the visible crosshatch of old games and print.

Why does my dithered image look too dark?

Two likely causes. Atkinson discards part of the error, so midtones drift darker by design. Or you are dithering in gamma space instead of linear light, which pulls midtones down. Try Floyd-Steinberg and check whether the tool works in linear light.

Does dithering make files smaller?

Not usually. It reduces the number of colors, but the dot texture is high-frequency noise that PNG and JPEG compress poorly. Sometimes a dithered 1-bit PNG is larger than the plain grayscale original. Measure it.

Why does a 4-level palette need less obvious dithering than 1-bit?

With four levels the largest gap the dither has to bridge is one quarter of the range instead of the whole range. Smaller gaps need fewer, smaller dots, so the grain is much subtler.

Can I use a custom palette?

Yes. Any dither method works with an arbitrary set of colors; the nearest-color step just searches your custom set instead of a fixed one. Error diffusion then spreads the per-channel difference the same way it does for grayscale.