Dither

Dither is a high-performance Elixir library for image processing and dithering, powered by a Rust NIF using Rustler. It wraps the excellent dither crate to provide fast, high-quality dithering algorithms.

Features

Showcase

Below are examples of Dither in action, generated from a single 1200x1200px source image of my cat.

Original Image (Resized)

Original Resized

Grayscale Dithering

Jarvis (1-bit) Stucki (4-bit)
Jarvis 1-bitStucki 4-bit

Color Dithering (Custom Palettes)

CGA Palette (Atkinson) Websafe Palette (Sierra) Crayon Palette (Floyd-Steinberg)
CGA PaletteWebsafe PaletteCrayon Palette

Installation

Add dither to your list of dependencies in mix.exs:

def deps do
  [
    {:dither, "~> 0.2.3"}
  ]
end

Building from Source

By default, Dither uses RustlerPrecompiled to provide binaries for common platforms. If you need to build the NIF from source (e.g., for an unsupported architecture or for development), you must have Rust installed and set the DITHER_BUILD environment variable:

DITHER_BUILD=true mix compile

Usage

All public functions in the Dither module return or accept a %Dither{} struct, which tracks the internal NIF reference along with image metadata.

Basic Example

# Load an image
image = Dither.load!("input.png")

# Inspect metadata
IO.inspect(image.size)      # {width, height}
IO.inspect(image.channels)  # 1 (grayscale) or 3 (RGB)

# Dither and save
image
|> Dither.grayscale!()
|> Dither.dither!(algorithm: :atkinson)
|> Dither.save!("output.png")

Color Dithering with Custom Palettes

image = Dither.load!("photo.jpg")

# Dither to the 16-color CGA palette
image
|> Dither.dither!(palette: :cga)
|> Dither.save!("retro_photo.png")

# Dither to a custom hex-based palette
image
|> Dither.dither!(palette: ["#000000", "#FF0000", "#00FF00", "#0000FF"])
|> Dither.save!("custom_colors.png")

Dithering Options

The dither/2 function supports the following options:

Supported Algorithms

Bit Depth

The :bit_depth option controls the quantization level. For example:

The Dither Struct

%Dither{
  ref: reference(),      # The NIF resource reference
  size: {u32, u32},      # {width, height} tuple
  channels: 1 | 3        # Number of color channels
}

License

This project is licensed under the MIT License - see the LICENSE file for details.