I want to display rich, vibrant images on my theoretical fancy custom display, but due to budget constraints, it displays everything in 3-bit colour! Whilst Regular Dithering would work, I don't want to sacrifice resolution, so I would like my images to be dithered through time!


Provided an Input Image, I would like you to show me several 3-bit color versions of that image, such that the average colour of all images is the original image.


You must take an image as input.

You may either animate the image (Return a GIF, Video, or on the screen), or take time as an additional input. If time is taken as input, the output must be Deterministic for a given image and time, and must return as a static image.


Girl with Pearl Earing

From Wikimedia Commons

Looks kind of like TV static Static

A lot of quality was lost between recording the output and converting it to a gif, thus a still has also been provided


The victory condition is , as per previously stated budget constraints.

Final Notes

Please consider the risk of photo-sensitivity when uploading an answer, and keep images to either external links, or wrapped in a spoiler. Videos of your solution running are not required, but are welcome.

  • 2
    \$\begingroup\$ What does 3-bit color means? How should I calculate average color? Will input image always use RGB color space? \$\endgroup\$
    – tsh
    Commented Dec 1, 2021 at 5:22
  • 2
    \$\begingroup\$ I think these would be helpful. Would you mind to edit these into the question itself? \$\endgroup\$
    – tsh
    Commented Dec 1, 2021 at 8:37
  • 1
    \$\begingroup\$ @theorist As stated in I/O, the output must either be animated, such as the first option in the spoiler, or a static output for a given time input. Both the example images provided are 3-bit (Ignoring the aliasing artifacts in the GIF) \$\endgroup\$
    – ATaco
    Commented Dec 1, 2021 at 9:19
  • 1
    \$\begingroup\$ You should have further constraints on what counts as dithering, as otherwise something like f=lambda i,t:[int(p>t%255)for p in i] is a valid submission \$\endgroup\$
    – AnttiP
    Commented Dec 1, 2021 at 10:24
  • 2
    \$\begingroup\$ @AnttiP I did consider that as a solution, and whilst it's not the most visually interesting answer, it's not that much more complex than p>rand(), and enforcing interesting solutions is difficult. \$\endgroup\$
    – ATaco
    Commented Dec 1, 2021 at 11:03

2 Answers 2


Wolfram Language (Mathematica), 24 bytes


Try it online!

Input [image,time], where image is a 3-channel RGB Image, and outputs a frame.

A fairly straightforward approach: output whenever the floor of the accumulated value increases. Mathematica's Images support arithmetic and can contain values of any size, but are clamped between 0 and 1 when displayed.

For the image in OP, a GIF output of t=1,2,...,255 can be viewed here (caution: blocks of flashing colors).
Averaging the frames:
enter image description here


Perl 5 -ap, 110 bytes


Can't try it online!

...but instead you can create an 8 frames animated GIF image with:

echo 'srand(7);$F[3]=1;$_=(map{splice@b,rand@b,1}@b=((1)x($o=int$_*8/256),(0)x(8-$o)))[$ENV{F}]for@F[4..$#F];$_="@F\n"' > program.pl
wget -N -O img.jpg "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Johannes_Vermeer_%281632-1675%29_-_The_Girl_With_The_Pearl_Earring_%281665%29.jpg/335px-Johannes_Vermeer_%281632-1675%29_-_The_Girl_With_The_Pearl_Earring_%281665%29.jpg"
convert -compress none img.jpg img.ppm
perl -i -pe's/\n/ /' img.ppm 
for f in {0..7};do cat img.ppm|F=$f perl -ap program.pl > img-frame$f.ppm;done  #~10sec
convert -delay 1 -loop 0 img-frame*.ppm img-animated.gif
xdg-open img-animated.gif

The program.pl reads the one line input (the example image of this challenge converted to the Plain PPM format) from STDIN and the frame number 0-7 (the time) from the environment variable F. The above commands works with bash shell, wget, the convert program from ImageMagick and xdg-open or any image viewer capable of viewing animated GIF images. To change to 16 frames, replace 7 with 15 and the two 8's with 16. Animated GIF image: https://drive.google.com/file/d/1s5WDGjwKLowdmildkYxUWGOWpRjS-Av6/view?usp=sharing


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.