Blue Noise

August 6, 2026 ยท View on GitHub

Blue Noise

Black and white image dithering using blue noise, plus a void-and-cluster generator for the noise itself

Turn a photograph into two colors without the crosshatch of an ordered dither.

Source photograph The same photograph dithered with blue noise

Install

cargo add blue-noise

Quickstart

use blue_noise::{
    BlueNoiseConfig, BlueNoiseGenerator, BlueNoiseTexture, Color, DitherOptions, apply_dithering,
    save_blue_noise_to_png,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = BlueNoiseConfig {
        width: 64,
        height: 64,
        seed: Some(42),
        ..Default::default()
    };
    let result = BlueNoiseGenerator::new(config)?.generate()?;
    save_blue_noise_to_png(&result, "blue-noise.png")?;

    let noise = BlueNoiseTexture::load("blue-noise.png")?;
    apply_dithering(
        "photo.jpg",
        "photo-dithered.png",
        &noise,
        DitherOptions {
            foreground: Color::from_hex("#1447e5")?,
            contrast: Some(1.2),
            ..Default::default()
        },
    )?;

    Ok(())
}

apply_dithering_to_image takes and returns an in-memory image if you would rather not touch the filesystem.

CLI

cargo install blue-noise
# Write a 128 by 128 tileable texture to blue-noise.png
blue-noise generate --size 128 --verbose

# Threshold a photo against it
blue-noise dither -i photo.jpg -o photo-dithered.png
FlagDefaultDescription
--sigma <f32>1.9Gaussian sigma, higher spreads points further apart
--seed <u32>Seed for a reproducible texture
--noise <path>blue-noise.pngTexture the dither thresholds against
--contrast <f32>Contrast adjustment, above 1 for more

--width and --height override --size for a non-square texture, and resize the output when dithering. Full lists are in blue-noise generate --help and blue-noise dither --help.

Notes

  • Distances wrap at the edges, so a texture tiles seamlessly across an image of any size.
  • Power-of-two sizes run their Gaussian blur through an FFT, roughly halving generation time. Generate once and reuse the file.
  • Uses the void-and-cluster algorithm from Ulichney (1993), building on Ulichney (1988).
  • blue-noise-typescript is the same dithering as a Node CLI, published on npm.
  • API documentation is on docs.rs.

License

MIT


Crafted by Matthew Blode