Our first method handles still images in most popular formats — PNG, JPG and so forth — and outputs a BMP image suitable for CircuitPython use. BMP is frequently used in microcontroller environments because it’s easy to decode.

This approach requires:

  • A desktop or laptop computer
  • Some familiarity with command line usage
  • Python 2 or 3 and the PIL or Pillow library

This method does not crop or resize images for the matrix! The source material must match the final size you intend to use. Sometimes you want images smaller or larger than the matrix, to scroll and move around. That’s fine, and this method will handle it.


From the command line, make sure you have the Python Imaging Library (PIL) or Pillow installed. For existing Python users, you’d type:

pip install pillow

This will either download and install the imaging library, or you might get a “Requirement already satisfied” message, which is fine.

Then download our image conversion script… you can use wget or curl from the command line if one of those is installed on your system. Either way, this should be typed (or copied-and-pasted) as a single unbroken line, regardless how it may appear formatted in your web browser right now):

wget https://raw.githubusercontent.com/adafruit/Adafruit_Media_Converters/master/protomatter_dither.py


curl https://raw.githubusercontent.com/adafruit/Adafruit_Media_Converters/master/protomatter_dither.py > protomatter_dither.py

or you can download it from your browser here:


It’s easiest if the conversion script and your images are in the same directory. If not…you should “cd” to the directory containing the images and type the relative path to the script, not the other way around. The script isn’t terribly robust with handling relative paths.

But first: what BMP variant will your project require? In CircuitPython, displayio.OnDiskBitmap prefers full-color 24-bit RGB images, while adafruit_imageload.load works with 8-bit “palettized” images. Look at your project’s source code for insights. The Matrix Creature Eyes project, for example, uses 8-bit palette images.

The protomatter_dither.py script accepts a list of input file names. BUT…if you want 8-bit palette BMP output, the list should be preceded by an “8”.

Let’s suppose you have three images to convert, a mix of PNG and JPG files called foo.png, bar.jpg and baz.png.

If you want 24-bit full color output, invoke the script like this:

python protomatter_dither.py foo.png bar.jpg baz.png

For 8-bit palette output, insert an “8” before the file list, like so:

python protomatter_dither.py 8 foo.png bar.jpg baz.png

The script will output a BMP file for each input file, with “-processed” added to the filename — for example, “foo.png” will result in an output file called “foo-processed.bmp”. The original file remains there, unharmed. You can then rename the output file to whatever you want and copy it to the CIRCUITPY drive of your microcontroller board loaded with CircuitPython firmware..

The BMPs will look very dark on your computer…but they’ll appear normal on the matrix! The script has to compensate for the lack of gamma correction there.

Occasionally these BMPs will need some manual touch-ups. The Matrix Eyes project, for example, relies on one very specific color being transparent…but, because the Python script applies dithering, occasionally it leaves a few dots in what should be the transparent areas.

You’ll need an image editor that can load and save BMP images (such as Photoshop, but there are many others, some free) … and, importantly, you must save the BMP as the exact same variant that you loaded, 8- or 24-bit, uncompressed. Some programs might change these details, so make sure you’re getting the right thing before committing to a big project.

This guide was first published on Oct 19, 2020. It was last updated on Mar 08, 2024.

This page (Still Images Using Python) was last updated on Mar 08, 2024.

Text editor powered by tinymce.