Documentation | Build Status |
---|---|
A dithering / digital halftoning package inspired by Lucas Pope's Obra Dinn and Surma's blogpost of the same name. Check out the gallery for an overview of all currently implemented algorithms.
To install this package and its dependencies, open the Julia REPL and run
julia> ]add DitherPunk
using DitherPunk
using Images
using TestImages
img = testimage("fabio_gray_256")
d = dither(img) # apply default algorithm: FloydSteinberg()
d = dither(img, Bayer()) # apply algorithm of choice
dither!(img) # or in-place modify image
dither!(img, Bayer()) # with the algorithm of your choice
If no color palette is provided, DitherPunk will apply binary dithering to each color channel of the input:
Error diffusion | Ordered dithering | Digital halftoning |
---|---|---|
Any of the 29 implemented algorithms can be used.
All error diffusion, ordered dithering and halftoning methods support custom color palettes. Define your own palette or use those from ColorSchemes.jl:
using ColorSchemes
cs = ColorSchemes.flag_us
dither(img, cs)
flag_us |
PuOr_6 |
websafe |
---|---|---|
DitherPunk also lets you generate optimized color palettes for each input image:
ncolors = 8
dither(img, ncolors)
2 colors | 8 colors | 32 colors |
---|---|---|
Dithering in custom colors is supported by all error diffusion, ordered dithering and halftoning methods:
dither(img, Atkinson(), cs)
dither(img, Atkinson(), ncolors)
Images can also be printed using Unicode Braille Patterns
braille(img, Bayer())
braille(img, Bayer(); invert=true)
⠕⠅⠅⠅⠕⠅⠕⠅⠅⠅⠅⠅⠅⠅⠅⠅⠅⠅⠕⠅⠕⠅⠕⢅⠕⠅⠕⢅⠕⠅⠕⠅⠅⠅⠅⠅⠅⠅⠕⠅⠁⠅⠁⠅⠁⠅⠁⠅⠁⠅⠁⠅⣪⣺⣺⣺⣪⣺⣪⣺⣺⣺⣺⣺⣺⣺⣺⣺⣺⣺⣪⣺⣪⣺⣪⡺⣪⣺⣪⡺⣪⣺⣪⣺⣺⣺⣺⣺⣺⣺⣪⣺⣾⣺⣾⣺⣾⣺⣾⣺⣾⣺⣾⡂
⠕⢅⠅⠅⠕⠅⠕⠅⠅⠅⠁⠅⠁⠅⠁⠅⠁⠅⠕⠅⠕⢅⢕⢕⢕⠅⠕⠅⢕⢅⠕⢅⠅⠅⠅⠅⠅⠅⠅⠅⠅⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⣪⡺⣺⣺⣪⣺⣪⣺⣺⣺⣾⣺⣾⣺⣾⣺⣾⣺⣪⣺⣪⡺⡪⡪⡪⣺⣪⣺⡪⡺⣪⡺⣺⣺⣺⣺⣺⣺⣺⣺⣺⣺⣾⣻⣾⣻⣾⣻⣾⣻⣾⡃
⠕⢅⠅⠅⠕⠅⠕⠅⠅⠅⠁⠅⠁⠅⠁⠅⠅⠅⠅⢅⢕⢅⢕⢥⠕⢕⢕⢅⢕⢅⠕⠅⠅⠅⠅⠅⠁⠅⠁⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⣪⡺⣺⣺⣪⣺⣪⣺⣺⣺⣾⣺⣾⣺⣾⣺⣺⣺⣺⡺⡪⡺⡪⡚⣪⡪⡪⡺⡪⡺⣪⣺⣺⣺⣺⣺⣾⣺⣾⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⣻⣾⡃
⠕⠅⠅⠅⠕⠅⠕⠅⠅⠅⠅⠅⠅⠅⠁⠅⠅⢵⢝⢵⢽⢽⢝⢵⢽⢽⢝⢕⠕⢕⠕⠕⠕⢅⠑⠄⠁⠅⠁⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⣪⣺⣺⣺⣪⣺⣪⣺⣺⣺⣺⣺⣺⣺⣾⣺⣺⡊⡢⡊⡂⡂⡢⡊⡂⡂⡢⡪⣪⡪⣪⣪⣪⡺⣮⣻⣾⣺⣾⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⣻⣾⡃
⠕⠅⠅⠅⠕⠅⠕⠅⠅⠅⠅⠅⠅⠅⠅⢕⢝⢵⢝⢝⢕⢅⢅⢅⠕⠅⠅⠕⢕⢅⠅⠅⠅⢅⠕⠅⠅⠕⠁⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⣪⣺⣺⣺⣪⣺⣪⣺⣺⣺⣺⣺⣺⣺⣺⡪⡢⡊⡢⡢⡪⡺⡺⡺⣪⣺⣺⣪⡪⡺⣺⣺⣺⡺⣪⣺⣺⣪⣾⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⣻⣾⡃
⠕⢅⠅⠅⠁⠅⠁⠅⠁⠅⠅⠅⠅⢅⢕⢕⠝⠅⠕⠅⠅⠅⠅⢕⠅⢕⠅⠄⠁⠕⠁⠅⠁⠅⠁⠅⠁⠅⢕⢅⠅⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⣪⡺⣺⣺⣾⣺⣾⣺⣾⣺⣺⣺⣺⡺⡪⡪⣢⣺⣪⣺⣺⣺⣺⡪⣺⡪⣺⣻⣾⣪⣾⣺⣾⣺⣾⣺⣾⣺⡪⡺⣺⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⡃
⠕⢅⠅⠅⠁⠅⠕⠅⠅⠅⠅⠅⠅⢕⠕⢅⠕⠅⠁⠅⠅⠅⠁⠅⠅⠅⠁⠅⠅⠅⠁⠅⠁⠄⠅⢅⠅⠅⠁⠅⠑⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⣪⡺⣺⣺⣾⣺⣪⣺⣺⣺⣺⣺⣺⡪⣪⡺⣪⣺⣾⣺⣺⣺⣾⣺⣺⣺⣾⣺⣺⣺⣾⣺⣾⣻⣺⡺⣺⣺⣾⣺⣮⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⡃
⠕⢅⠅⠅⠁⠅⠕⠅⠅⠅⠅⠅⢕⢅⠅⢅⠅⠅⠁⢕⢽⣵⢵⢵⢵⢵⢕⢵⢕⢅⢅⢅⢵⢵⢕⢕⢕⢕⠕⠄⠁⠅⠅⠅⠁⠄⠁⠄⠁⠄⠁⠄⣪⡺⣺⣺⣾⣺⣪⣺⣺⣺⣺⣺⡪⡺⣺⡺⣺⣺⣾⡪⡂⠊⡊⡊⡊⡊⡪⡊⡪⡺⡺⡺⡊⡊⡪⡪⡪⡪⣪⣻⣾⣺⣺⣺⣾⣻⣾⣻⣾⣻⣾⡃
⠕⢅⠕⠅⠁⠅⠕⠅⠅⠅⠕⢵⢕⠅⠅⠅⠅⠄⠕⢕⢽⢽⢿⣽⢿⢽⢿⣽⢿⢽⢿⢽⢿⢽⢝⢵⢕⢕⠕⠅⠅⠅⠁⠅⠅⠅⠁⠅⠁⠅⠁⠄⣪⡺⣪⣺⣾⣺⣪⣺⣺⣺⣪⡊⡪⣺⣺⣺⣺⣻⣪⡪⡂⡂⡀⠂⡀⡂⡀⠂⡀⡂⡀⡂⡀⡂⡢⡊⡪⡪⣪⣺⣺⣺⣾⣺⣺⣺⣾⣺⣾⣺⣾⡃
⠕⠅⠕⠅⠁⠅⠕⢅⠅⢅⢕⢕⠕⢅⠅⠅⠅⠅⠅⠅⢝⢽⢿⢽⢿⢽⢿⢽⢿⢽⢿⣽⢿⢽⢝⢵⢝⢕⠅⠄⠁⠅⠕⢅⢅⠅⠅⠅⠁⠅⠁⠄⣪⣺⣪⣺⣾⣺⣪⡺⣺⡺⡪⡪⣪⡺⣺⣺⣺⣺⣺⣺⡢⡂⡀⡂⡀⡂⡀⡂⡀⡂⡀⠂⡀⡂⡢⡊⡢⡪⣺⣻⣾⣺⣪⡺⡺⣺⣺⣺⣾⣺⣾⡃
⠕⠅⠕⠅⠁⢅⢕⢕⢝⢽⢝⢅⢕⢅⠅⠄⠕⠅⠁⢵⢝⢽⢽⢽⢿⣽⢿⢽⢿⣽⢿⣽⢿⢽⢝⢵⢝⢕⠕⠅⠁⠅⠕⢕⠕⠅⠅⠅⠁⠄⠁⠄⣪⣺⣪⣺⣾⡺⡪⡪⡢⡂⡢⡺⡪⡺⣺⣻⣪⣺⣾⡊⡢⡂⡂⡂⡀⠂⡀⡂⡀⠂⡀⠂⡀⡂⡢⡊⡢⡪⣪⣺⣾⣺⣪⡪⣪⣺⣺⣺⣾⣻⣾⡃
⠕⠅⠕⠅⠑⢅⠕⢅⢝⢵⢕⢵⢕⠅⠁⠅⠁⠄⠁⢵⢝⢝⠝⠝⠝⠝⠟⠝⢿⢽⢽⢽⠝⠝⠝⠅⠁⢅⢕⠅⠁⠄⠁⠅⠑⠅⠁⠅⠅⠄⠁⠄⣪⣺⣪⣺⣮⡺⣪⡺⡢⡊⡪⡊⡪⣺⣾⣺⣾⣻⣾⡊⡢⡢⣢⣢⣢⣢⣠⣢⡀⡂⡂⡂⣢⣢⣢⣺⣾⡺⡪⣺⣾⣻⣾⣺⣮⣺⣾⣺⣺⣻⣾⡃
⠕⠅⠕⠅⠕⢅⢝⢵⢝⢵⢽⢕⢝⠅⠅⠄⠁⠄⢑⢽⢽⢵⢕⢵⢕⢵⢕⢵⢝⢽⢿⢕⢕⢕⢕⢕⢕⢕⢕⢕⢕⠅⠁⠅⠁⠅⠅⠅⠅⠅⠁⠄⣪⣺⣪⣺⣪⡺⡢⡊⡢⡊⡂⡪⡢⣺⣺⣻⣾⣻⡮⡂⡂⡊⡪⡊⡪⡊⡪⡊⡢⡂⡀⡪⡪⡪⡪⡪⡪⡪⡪⡪⡪⣺⣾⣺⣾⣺⣺⣺⣺⣺⣾⡃
⠕⠅⠕⠅⠕⢕⢽⢕⢝⢽⢝⢕⢕⢅⠅⠄⠅⠄⠑⢽⢽⢽⢿⣿⢿⣽⢿⢽⢝⢽⢝⢕⢝⢽⢝⢽⢽⢽⢝⢅⢝⠕⠁⠄⠑⢅⠕⢅⠁⠅⠁⠄⣪⣺⣪⣺⣪⡪⡂⡪⡢⡂⡢⡪⡪⡺⣺⣻⣺⣻⣮⡂⡂⡂⡀⠀⡀⠂⡀⡂⡢⡂⡢⡪⡢⡂⡢⡂⡂⡂⡢⡺⡢⣪⣾⣻⣮⡺⣪⡺⣾⣺⣾⡃
⠕⠅⠕⠅⠕⢅⢝⢵⢽⢵⢝⢝⢝⢅⠕⢅⠕⠅⠁⢕⢝⢽⢿⣽⢿⣽⢿⢽⢝⢽⢟⢕⢕⢽⢝⢽⢝⢕⢕⢅⠝⠅⠁⠄⠑⢕⢕⠅⠕⠅⠁⠄⣪⣺⣪⣺⣪⡺⡢⡊⡂⡊⡢⡢⡢⡺⣪⡺⣪⣺⣾⡪⡢⡂⡀⠂⡀⠂⡀⡂⡢⡂⡠⡪⡪⡂⡢⡂⡢⡪⡪⡺⣢⣺⣾⣻⣮⡪⡪⣺⣪⣺⣾⡃
⠕⠅⠕⠕⠕⢅⢽⢵⢝⢽⠝⢕⢕⢕⢕⢅⠁⠀⠁⢕⢝⢽⢝⢽⢽⢽⢿⢽⢝⢽⢝⢕⢝⢵⢝⢕⢝⢕⠕⢅⠁⠀⠁⠄⠁⠕⠕⠅⠅⠅⠁⠄⣪⣺⣪⣪⣪⡺⡂⡊⡢⡂⣢⡪⡪⡪⡪⡺⣾⣿⣾⡪⡢⡂⡢⡂⡂⡂⡀⡂⡢⡂⡢⡪⡢⡊⡢⡪⡢⡪⣪⡺⣾⣿⣾⣻⣾⣪⣪⣺⣺⣺⣾⡃
⠕⠅⠅⠅⠕⢵⢟⢵⢽⢝⢕⢕⢕⢕⠕⠅⠁⠀⠁⢅⢕⢕⢝⢽⢿⢽⢽⢵⢝⢝⠝⢕⢝⢕⢝⢕⠝⢕⢕⢅⠁⠀⠁⠄⠁⠅⠕⠅⠅⠄⠁⠄⣪⣺⣺⣺⣪⡊⡠⡊⡂⡢⡪⡪⡪⡪⣪⣺⣾⣿⣾⡺⡪⡪⡢⡂⡀⡂⡂⡊⡢⡢⣢⡪⡢⡪⡢⡪⣢⡪⡪⡺⣾⣿⣾⣻⣾⣺⣪⣺⣺⣻⣾⡃
⠕⢅⠕⢕⢕⢝⢟⢽⢝⢵⢕⢵⢕⠕⠅⠅⠁⠀⠁⢅⢝⢕⢝⢽⢝⢽⢝⢽⢝⢕⢕⢕⢝⢕⢕⢕⠕⢕⠕⠅⠁⠀⠁⠀⠁⠅⠅⠅⠁⠅⠁⠄⣪⡺⣪⡪⡪⡢⡠⡂⡢⡊⡪⡊⡪⣪⣺⣺⣾⣿⣾⡺⡢⡪⡢⡂⡢⡂⡢⡂⡢⡪⡪⡪⡢⡪⡪⡪⣪⡪⣪⣺⣾⣿⣾⣿⣾⣺⣺⣺⣾⣺⣾⡃
⠕⢅⢕⢕⢝⢝⢝⢽⢽⢵⢝⢕⠅⠅⠅⠅⠁⠄⠁⠀⠝⢵⢝⢽⢝⢵⢵⢵⢵⢭⢝⢵⢕⢕⢕⢕⠕⢕⠕⢕⠅⠄⠁⠀⠁⠅⠅⠅⠅⠅⠕⠅⣪⡺⡪⡪⡢⡢⡢⡂⡂⡊⡢⡪⣺⣺⣺⣺⣾⣻⣾⣿⣢⡊⡢⡂⡢⡊⡊⡊⡊⡒⡢⡊⡪⡪⡪⡪⣪⡪⣪⡪⣺⣻⣾⣿⣾⣺⣺⣺⣺⣺⣪⡂
⠕⢝⢕⢕⢕⢽⢽⢽⢽⢽⢝⢕⢕⠅⠅⠅⠁⠀⠁⠀⠁⠑⠝⢕⢝⢽⢝⢵⢝⢕⢕⢕⢕⢕⢕⢕⠕⢅⢕⢅⠕⢕⢕⢄⠅⠀⠁⠅⠁⠅⠁⠅⣪⡢⡪⡪⡪⡂⡂⡂⡂⡂⡢⡪⡪⣺⣺⣺⣾⣿⣾⣿⣾⣮⣢⡪⡢⡂⡢⡊⡢⡪⡪⡪⡪⡪⡪⡪⣪⡺⡪⡺⣪⡪⡪⡻⣺⣿⣾⣺⣾⣺⣾⡂
⠕⢵⢕⢵⢝⢽⢽⣽⢝⢕⢕⢕⠝⠅⠅⠅⠁⠄⠁⠀⠁⠀⠑⢅⠝⢽⢝⢽⢿⢽⢿⢽⢝⢕⠕⢅⢕⢕⢕⢕⢕⢕⢝⢕⢕⢕⠅⠄⠁⠀⠁⠄⣪⡊⡪⡊⡢⡂⡂⠂⡢⡪⡪⡪⣢⣺⣺⣺⣾⣻⣾⣿⣾⣿⣮⡺⣢⡂⡢⡂⡀⡂⡀⡂⡢⡪⣪⡺⡪⡪⡪⡪⡪⡪⡢⡪⡪⡪⣺⣻⣾⣿⣾⡃
⢕⢵⢽⣽⢿⢽⢝⢝⢵⢕⠝⠕⠅⢅⠅⠅⠁⠅⠁⠄⠁⠀⠁⠅⢕⢕⠝⢕⠝⠝⠝⠕⠝⢅⢕⢕⢕⢕⢝⢕⢝⢕⢝⢕⢝⢕⢝⢅⠁⠄⠁⠄⡪⡊⡂⠂⡀⡂⡢⡢⡊⡪⣢⣪⣺⡺⣺⣺⣾⣺⣾⣻⣾⣿⣾⣺⡪⡪⣢⡪⣢⣢⣢⣪⣢⡺⡪⡪⡪⡪⡢⡪⡢⡪⡢⡪⡢⡪⡢⡺⣾⣻⣾⡃
⢽⢽⢟⢝⢝⢵⢽⢝⢕⠅⠕⠅⠁⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⢄⠕⢕⢕⢵⢕⢵⢕⢵⢕⢵⢝⢵⢝⢵⢝⢵⢝⢕⢝⢕⢝⢕⢕⢕⢕⠄⠁⠄⡂⡂⡠⡢⡢⡊⡂⡢⡪⣺⣪⣺⣾⣺⣾⣻⣾⣻⣾⣻⣾⣻⣾⡻⣪⡪⡪⡊⡪⡊⡪⡊⡪⡊⡢⡊⡢⡊⡢⡊⡢⡪⡢⡪⡢⡪⡪⡪⡪⣻⣾⡃
⢝⢽⢝⢽⢟⢽⢝⢵⢕⠅⠁⠄⠅⠄⠁⠄⠁⠄⠁⠄⠁⠀⠁⠅⠕⢕⢝⢕⢝⢽⢝⢵⢝⢵⢽⢽⢽⢽⢝⢵⢝⢵⢝⢵⢝⢵⢝⢕⢝⢕⠅⠄⡢⡂⡢⡂⡠⡂⡢⡊⡪⣺⣾⣻⣺⣻⣾⣻⣾⣻⣾⣻⣾⣿⣾⣺⣪⡪⡢⡪⡢⡂⡢⡊⡢⡊⡂⡂⡂⡂⡢⡊⡢⡊⡢⡊⡢⡊⡢⡪⡢⡪⣺⡃
⠝⢽⢝⢽⢝⢽⠝⠕⠅⠅⠅⠅⠁⠄⠁⠄⠁⠅⠁⠄⠁⠀⠁⠄⢕⢵⢝⢵⢝⢽⢝⢽⢽⢽⢽⢽⢽⢵⢕⢽⢝⢽⢝⢵⢝⢵⢝⢵⢝⢕⢕⠅⣢⡂⡢⡂⡢⡂⣢⣪⣺⣺⣺⣺⣾⣻⣾⣻⣾⣺⣾⣻⣾⣿⣾⣻⡪⡊⡢⡊⡢⡂⡢⡂⡂⡂⡂⡂⡂⡊⡪⡂⡢⡂⡢⡊⡢⡊⡢⡊⡢⡪⡪⡂
⠝⠽⠝⠵⠝⠕⠕⠅⠕⠅⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⠁⠄⠁⠅⠕⠽⠝⠽⠝⠵⠝⠽⠽⠽⠿⠽⠽⠵⠝⠵⠝⠵⠝⠵⠝⠵⠝⠵⠝⠵⠝⠅⠢⠂⠢⠊⠢⠪⠪⠺⠪⠺⠾⠻⠾⠻⠾⠻⠾⠻⠾⠻⠾⠻⠾⠺⠪⠂⠢⠂⠢⠊⠢⠂⠂⠂⠀⠂⠂⠊⠢⠊⠢⠊⠢⠊⠢⠊⠢⠊⠢⠊⠢⠂
For a more in-depth introduction, take a look at the docs.
Check out our talk at JuliaCon 2022 for a demonstration of the package:
- Error diffusion:
FloydSteinberg
(default)JarvisJudice
Atkinson
Stucki
Burkes
Sierra
TwoRowSierra
SierraLite
Fan93
ShiauFan
ShiauFan2
SimpleErrorDiffusion
- Ordered dithering:
Bayer
- Halftoning:
ClusteredDots
CentralWhitePoint
BalancedCenteredPoint
Rhombus
- Threshold maps from ImageMagick:
IM_checks
IM_h4x4a
IM_h6x6a
IM_h8x8a
IM_h4x4o
IM_h6x6o
IM_h8x8o
IM_c5x5
IM_c6x6
IM_c7x7
- Other:
ClosestColor
ConstantThreshold
WhiteNoiseThreshold
Share your creations in the discussions tab and leave a GitHub Issue if you know of any cool algorithms you'd like to see implemented! 🔬🔧