Programming the LoL Shield using animated GIFs


A couple of weeks ago, I was hacking on the LoL Shield with Nathan Rosenquist, when we realized that it was really time consuming to use the spreadsheet program to build animations. Never fear, a quick python script later and we could generate animations automatically from animated gifs.
Using the program, you can take black & white 14×9 GIF animations of (probably) any length, such as the following one by Nathan:

and get some code ready for the LoLing:

uint16_t ripple[][9] PROGMEM = {
 { 520 , 1028 , 2050 , 2050 , 2114 , 2050 , 2050 , 1028 , 520 , },
 { 2050 , 4097 , 4097 , 8256 , 8352 , 8256 , 4097 , 4097 , 2050 , },
 { 8192 , 8192 , 224 , 272 , 272 , 272 , 224 , 8192 , 8192 , },
 { 0 , 224 , 272 , 520 , 520 , 520 , 272 , 224 , 0 , },
 { 224 , 272 , 520 , 1028 , 1028 , 1028 , 520 , 272 , 224 , },
};

Here’s the python source, have fun! It requires Python and the Python Imaging Library (PIL):

#!/usr/bin/python
# Python script to convert a 14x9 pixel animated gif into a format that can
# be displayed on the LoLShield.
#
# Requires Python and the Python Imaging Library (PIL)
# It would be nice if this was available using a more common language.
 
import sys, os, Image
 
class ImageSequence:
    def __init__(self, im):
        self.im = im
    def __getitem__(self, ix):
        try:
            if ix:
                self.im.seek(ix)
            return self.im
        except EOFError:
            raise IndexError # end of sequence
 
# Open image
filename = sys.argv[1]
filenameBase = os.path.splitext(os.path.split(filename)[1])[0]
im = Image.open(filename)
 
# Print the variable declaration
print "uint16_t " + filenameBase + "[][9] PROGMEM = {"
 
# For each frame in the image, convert it to black & white, then into the
# LoLShield format
for frame in ImageSequence(im):
    # Convert to black and white
    converted = frame.convert("1")
 
    print " {",
    frameString = converted.tostring()
 
    # For each row in the image
    for row in range (0, 9):
        charA = ord(frameString[row*2])
        charB = ord(frameString[row*2 + 1])
 
        rowTotal = 0
        # Handle the first 8 bits
        for col in range (0, 8):
            shiftAmount = 7-col
            rowTotal += ((charA >> shiftAmount) & 1) * 2**col
        # Then the next 6
        for col in range (0, 6):
            shiftAmount = 7-col
            rowTotal += ((charB >> shiftAmount) & 1) * 2**(col+8)
        # And output the total for this row
        print rowTotal, ",",
    print "},"
print "};"
This entry was posted in tech. Bookmark the permalink.

7 Responses to Programming the LoL Shield using animated GIFs

  1. Pingback: LoL Shield Projects

  2. Pingback: LVL1 » Blog Archive » Fun with the LOLShield

  3. Frank G says:

    Very inspired by this. But i have a few noob questions.

    Is “filename” in the python script where i would replace with the name of the GIF file I want to convert?

    also where do i store the GIF file as reference? do i keep them in both arduino library and python path?

    • mahto says:

      Hi Frank! Glad you like the project. Did you end up figuring it out?

      The script actually looks for an image file name to be specified as a command line argument- so if you put both the script and the image in the same directory, just type this (assuming that you named the script converter.py):

      ./converter.py imagename.gif

      And it should work. I use linux, however it should be pretty similar to get working on OS X or Windows.

  4. Pingback: ? | We Saw a Chicken …

  5. scruss says:

    I got it to work under OS X, though the Imaging library was a fight.

    Since Arduino uses gcc, and gcc understands binary constants, if you use Linux you can use Netpbm on the command line to avoid all this python stuff:

    giftopnm file.gif | pgmtopbm -thresh | pnminvert | pnmflip -lr | pnmnoraw | tail +3 | sed 's/^/0b/;s/$/,/;'
    

    This outputs 9 lines of binary constants which sorta-kinda look like the image you’re displaying:

    0b00000011110000,
    0b00000111111000,
    0b00001111111100,
    0b00011111111000,
    0b00111111110000,
    0b00011111111000,
    0b00001111111100,
    0b00000111111000,
    0b00000011110000,
    

    You’ll need to lop off the last comma. It’s not that much work to alter this to handle multiple frames. You may also need to play with using pnminvert (which inverts the image, so lit LEDs become dark and vice versa) and pnmflip (which mirrors the image left to right).

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>