Preparing Images

The poi can display small GIF images with up to 16 colors (though two-color images — bitmaps — are much smaller and you can store more of them). Images are 16 pixels tall, and a maximum of 255 pixels wide (but can be as narrow as 1 pixel).

There’s not a whole lot of space on the Trinket. After the code stakes its claim, there’s little more than 1,700 bytes free for images. A 16-color GIF requires 48 bytes plus an additional 8 bytes per column. A 2-color (bitmap) GIF requires 6 bytes plus an additional 2 bytes/column. There’s enough space for a few carefully-crafted “pixel art” type images.

A tiny 16-pixel-high Welsh flag. I’m not even Welsh, but totally a sucker for anything with a cool dragon on it. Rawr.

The process for converting images for the poi is a little gritty right now, requiring a command-line tool written in Python. It also requires the Python Imaging Library (PIL).

Probably the least-bothersome way to do this right now is on a Raspberry Pi computer, where most of the tools are already built-in, though this requires some familiarity with the Linux operating system.

I'd like to make a more user-friendly tool for this in the future. But for the time being these steps remain a bit technical.

Installing and using Python varies from system to system. On the Raspberry Pi, Python is already installed by default, though PIL must be added manually:

sudo apt-get install python-imaging

Things will be entirely different on Windows or Mac or even on other Linux distributions. Unfortunately setting up Python is way beyond the scope of this guide, so you might Google ’round for tutorials elsewhere. If this gets too dry and technical, don’t fret…I suspect that given time other users will post some good poi-ready images to the Adafruit Forums.

So, let’s suppose we have this little Welsh dragon GIF image, 16 pixels tall by 26 pixels wide:

The top of the image will correspond to the tip of the poi. The flag of Wales traditionally has the dragon facing left, but it’s flipped here because the poi will “paint” the image left-to-right…and if you were swinging an actual physical flag through actual physical air, the dragon always faces the direction of motion (the example images also include a United States flag, and that one’s flipped for the same reason…you’ll see this with flags on the starboard side of an airplane too…part of international flag protocol).

ANYWAY, to convert this using the Python script, you’d type:

python convert.py wales.gif > graphics.h

Or you can convert a whole list of images:

python convert.py *.gif > graphics.h

The “> graphics.h” redirects the output of the convert.py script to the plain-text file graphics.h, which can then be incorporated into an Arduino sketch.

Inside the file you’ll see one or more sections like this:

// usa.gif -----------------------------------------------------------------

const uint8_t PROGMEM palette04[][3] = {
  {  56,  56,  56 },
  {  56,   0,   0 },
  {   0,   0,   0 },
  {   0,   3,  56 } };

const uint8_t PROGMEM pixels04[] = {
  0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22,
  0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X10, 0X10, 0X10, 0X10, 0X10, 0X10, 0X12, 0X22,
  0X33, 0X33, 0X33, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X30, 0X30, 0X30, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X33, 0X03, 0X03, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X30, 0X30, 0X30, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X33, 0X03, 0X03, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X30, 0X30, 0X30, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X33, 0X03, 0X03, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X30, 0X30, 0X30, 0X30, 0X10, 0X10, 0X12, 0X22,
  0X33, 0X33, 0X33, 0X30, 0X10, 0X10, 0X12, 0X22 };

Above is the data for an American flag…a four-entry color palette (white, red, black, blue) followed by the pixel data (packed two pixels per byte).

Then, near the bottom of the file, you’ll see a block like this:

const image PROGMEM images[] = {
  { PALETTE1 ,  100, (const uint8_t *)palette00, pixels00 },
  { PALETTE4 ,   48, (const uint8_t *)palette01, pixels01 },
  { PALETTE4 ,   54, (const uint8_t *)palette02, pixels02 },
  { PALETTE4 ,    1, (const uint8_t *)palette03, pixels03 },
  { PALETTE4 ,   24, (const uint8_t *)palette04, pixels04 },
  { PALETTE4 ,    9, (const uint8_t *)palette05, pixels05 },
  { PALETTE4 ,   26, (const uint8_t *)palette06, pixels06 }
};

This table holds references to all of the images in the file, along with their widths in pixels (height is always 16) and format (bitmap or up to 16 colors).

If you need to free up some program space in a hurry, you can just comment out or delete a line in this table…the compiler is smart enough to not include the corresponding image data in the final program.

Last updated on 2015-11-20 at 05.19.04 AM Published on 2015-07-13 at 11.53.55 AM