Dithering

Targets:
image
volume
Image Types:uint8, float32

Reduce the number of colors in an image using dithering techniques.

Dithering is like creating a newspaper photo - it uses patterns of dots to create the illusion of more colors than are actually present. When you have a limited color palette (like only black and white), dithering arranges these limited colors in patterns that trick your eye into seeing intermediate shades.

Think of it like pointillist paintings - up close you see individual dots, but from a distance they blend together to create smooth gradients and subtle color variations.

This transform works with ANY number of channels - it processes each channel independently, whether you have a standard RGB image (3 channels), RGBA with transparency (4 channels), multispectral satellite imagery (dozens of channels), or even single-channel grayscale images.

Arguments
method
random | ordered | error_diffusion
error_diffusion

Which dithering algorithm to use. Each has different characteristics:

  • "random": Adds random noise before quantization. Creates a grainy, film-like texture. Good for artistic effects or simulating old photographs.
  • "ordered": Uses a repeating pattern (Bayer matrix) to decide which pixels to darken. Creates distinctive crosshatch patterns. Fast and predictable. Common in old computer graphics and newspaper printing.
  • "error_diffusion": Most sophisticated method. When a pixel is made darker or lighter than it should be, the "error" is spread to neighboring pixels. Creates the most natural-looking results. Like using a fine brush. Default: "error_diffusion"
n_colors
int
2

How many different color levels to keep per channel. Must be between 2 and 256.

  • 2 = only black and white (or min/max values for each channel)
  • 4 = 4 levels of gray (or 4 levels per color channel)
  • 16 = 16 shades, creating a retro computer graphics look
  • 256 = full range, no reduction (but patterns still visible from dithering process) Lower values create more dramatic effects. Default: 2
color_mode
grayscale | per_channel
grayscale

How to handle color channels:

  • "per_channel": Each color channel (R, G, B, etc.) is dithered separately. Maintains color relationships but each channel gets its own pattern. Works with any number of channels.
  • "grayscale": First converts the image to grayscale (using standard luminance weights), then applies dithering, then expands back to the original number of channels. All color information is lost, but the dithering pattern is consistent across channels. Default: "grayscale"
error_diffusion_algorithm
floyd_steinberg | jarvis | stucki | atkinson | burkes | sierra | sierra_2row | sierra_lite
floyd_steinberg

Used only in "error_diffusion" method. Which specific algorithm:

  • "floyd_steinberg": The classic, invented in 1976. Spreads error to 4 neighbors. Good balance of quality and speed. Industry standard.
  • "jarvis": Jarvis-Judice-Ninke algorithm. Spreads error to 12 neighbors. Higher quality but 3x slower than Floyd-Steinberg.
  • "stucki": Similar to Jarvis but with different weights. Also 12 neighbors.
  • "atkinson": Created by Bill Atkinson for original Macintosh. Only spreads 75% of error, creating lighter images with more contrast.
  • "burkes": Spreads to 7 neighbors. Faster than Jarvis, better than Floyd-Steinberg.
  • "sierra": Spreads to 10 neighbors. Good quality, moderate speed.
  • "sierra_2row": Simplified Sierra using only 2 rows. Faster.
  • "sierra_lite": Minimal Sierra using only 3 neighbors. Very fast. Default: "floyd_steinberg"
bayer_matrix_size
2 | 4 | 8 | 16
4

Used only in "ordered" method. The size of the repeating pattern (2, 4, 8, or 16).

  • 2x2: Very visible checkerboard pattern
  • 4x4: Standard, good balance
  • 8x8: Finer pattern, less visible
  • 16x16: Very fine pattern, almost noise-like Default: 4
serpentine
bool
false

Used only in "error_diffusion" method. Whether to process rows in alternating directions (left-to-right, then right-to-left). This can reduce visible "worm" artifacts that sometimes appear as diagonal lines. Slightly slower. Default: False

noise_range
tuple[float, float]
[-0.5,0.5]

Used only in "random" method. How much random noise to add before quantization. Larger range = more variation in the dithering pattern. Range: (-1.0, 1.0). Default: (-0.5, 0.5)

p
float
0.5

Probability of applying this transform. Default: 0.5

Examples
>>> import numpy as np
>>> import albumentations as A
>>> # Prepare sample data
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>>
>>> # Black and white dithering with Floyd-Steinberg
>>> transform = A.Compose([
...     A.Dithering(
...         method="error_diffusion",
...         n_colors=2,
...         error_diffusion_algorithm="floyd_steinberg",
...         color_mode="grayscale",
...         p=1.0
...     )
... ])
>>> transformed = transform(image=image)
>>> dithered_image = transformed['image']  # Black and white dithered image
>>>
>>> # Ordered dithering with 16 colors per channel
>>> transform = A.Compose([
...     A.Dithering(
...         method="ordered",
...         n_colors=16,
...         bayer_matrix_size=8,
...         color_mode="per_channel",
...         p=1.0
...     )
... ])
>>> transformed = transform(image=image)
>>> dithered_image = transformed['image']  # Reduced color depth with Bayer pattern
>>>
>>> # Random dithering
>>> transform = A.Compose([
...     A.Dithering(
...         method="random",
...         n_colors=4,
...         noise_range=(-0.3, 0.3),
...         p=1.0
...     )
... ])
>>> transformed = transform(image=image)
>>> dithered_image = transformed['image']  # Noisy dithered appearance