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.
- Format Support: Load/save and encode/decode common image formats (PNG, JPEG, etc.).
- Transformations: Resize, rotate, flip, and grayscale conversion.
- Dithering: Support for 6 high-quality dithering algorithms.
- Native Efficiency: Heavy lifting is performed in Rust, while providing a clean, idiomatic Elixir interface.
Below are examples of Dither in action, generated from a single 1200x1200px
source image of my cat.
| Jarvis (1-bit) | Stucki (4-bit) |
|---|---|
![]() |
![]() |
| CGA Palette (Atkinson) | Websafe Palette (Sierra) | Crayon Palette (Floyd-Steinberg) |
|---|---|---|
![]() |
![]() |
![]() |
Add dither to your list of dependencies in mix.exs:
def deps do
[
{:dither, "~> 0.2.1"}
]
endBy 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 compileAll public functions in the Dither module return or accept a %Dither{}
struct, which tracks the internal NIF reference along with image metadata.
# 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")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")The dither/2 function supports the following options:
:algorithm: The dithering algorithm to use (default::sierra):bit_depth: The target color depth (default:1for black and white):palette: A list of colors to dither to. If provided,:bit_depthis ignored. Supported values:- List of RGB tuples:
[{255, 0, 0}, ...] - List of Hex strings:
["#FF0000", ...] - Predefined atoms:
:cga,:websafe,:crayon - Simple color atoms:
:black,:white,:red,:green,:blue,:yellow,:cyan,:magenta
- List of RGB tuples:
:floyd_steinberg:atkinson:stucki:burkes:jarvis:sierra(default)
The :bit_depth option controls the quantization level. For example:
bit_depth: 1(default): 2 colorsbit_depth: 2: 4 colorsbit_depth: 4: 16 colors
%Dither{
ref: reference(), # The NIF resource reference
size: {u32, u32}, # {width, height} tuple
channels: 1 | 3 # Number of color channels
}This project is licensed under the MIT License - see the LICENSE file for details.





